4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.gnu.org/licenses/gpl-2.0.html
23 * Copyright (c) 2022, Whamcloud.
26 * This file is part of Lustre, http://www.lustre.org/
33 # define __USE_ISOC99 1
34 # include <stdio.h> /* snprintf() */
35 # include <stdlib.h> /* abs() */
36 # include <inttypes.h> /* PRIu64 */
37 # include <ctype.h> /* isascii() */
39 # define __USE_XOPEN2K8 1
41 #include <linux/ctype.h>
44 #endif /* !__KERNEL__ */
46 #include <linux/types.h>
47 #include <linux/string.h>
48 #include <linux/unistd.h>
51 * sparse kernel source annotations
57 struct lgssd_ioctl_param {
65 __u64 send_token_size;
66 char __user *send_token;
68 char __user *reply_buf;
74 #define GSS_SOCKET_PATH "/tmp/svcgssd.socket"
75 #define RSI_DOWNCALL_MAGIC 0x6d6dd62a
76 #define RSI_DOWNCALL_PATH "sptlrpc/gss/rsi_info"
77 #define RSI_CACHE_NAME "rsicache"
79 struct rsi_downcall_data {
87 /* sid_val contains in_handle, in_token,
88 * out_handle, out_token
94 * gss_string_write() - write some string
96 * If string is empty, write single digit 0.
97 * Pad with a trailing space.
99 static inline void gss_string_write(char **dst, int *dstlen, const char *src)
108 ret = snprintf(cp, *dstlen, "0");
110 ret = snprintf(cp, *dstlen, "%s", src);
111 if (ret >= *dstlen) {
123 * gss_u64_write() - write some u64
125 static inline void gss_u64_write_string(char **dst, int *dstlen, uint64_t n)
133 ret = snprintf(cp, *dstlen, "%"PRIu64, n);
134 if (ret >= *dstlen) {
146 * gss_u64_write_hex() - write some u64 in hex
148 static inline void gss_u64_write_hex_string(char **dst, int *dstlen, uint64_t n)
156 ret = snprintf(cp, *dstlen, "0x%"PRIx64, n);
157 if (ret >= *dstlen) {
169 * gss_buffer_write() - write some buffer
171 static inline void gss_buffer_write(char **dst, int *dstlen,
172 const __u8 *src, int srclen)
181 if (len < sizeof(__u32)) {
186 /* write size of data */
190 len -= sizeof(__u32);
195 /* write data itself */
196 while (srclen && len) {
210 * gss_u32_write() - write some u32
212 static inline void gss_u32_write(char **dst, int *dstlen, __u32 val)
221 if (len < sizeof(__u32)) {
229 len -= sizeof(__u32);
236 static const char base64url_table[] =
237 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
239 #define BASE64URL_CHARS(nbytes) ((((nbytes) * 4) + 3 - 1) / 3)
242 * gss_base64url_encode() - base64url-encode some binary data
244 * Encode data using base64url encoding, i.e. the "Base 64 Encoding with URL
245 * and Filename Safe Alphabet" specified by RFC 4648. '='-padding isn't used,
246 * as it's unneeded and not required by the RFC.
247 * Pad with a trailing space.
249 static inline void gss_base64url_encode(char **dst, int *dstlen,
250 const __u8 *src, int srclen)
262 return gss_string_write(dst, dstlen, "");
264 for (i = 0; i < srclen; i++) {
267 ac = (ac << 8) | src[i];
271 *cp++ = base64url_table[(ac >> bits) & 0x3f];
273 } while (bits >= 6 && len > 0);
281 *cp++ = base64url_table[(ac << (6 - bits)) & 0x3f];
298 * gss_base64url_decode() - base64url-decode a string
300 * Decode a string using base64url encoding, i.e. the "Base 64 Encoding with
301 * URL and Filename Safe Alphabet" specified by RFC 4648. '='-padding isn't
302 * accepted, nor are non-encoding characters such as whitespace.
303 * String end is marked with a trailing space or '\n' or '\0'.
305 static inline int gss_base64url_decode(char **src, char *dst, int destsize)
307 int bits = 0, len = 0;
315 /* the single digit 0 is inserted if field is empty */
317 (*(cp + 1) == ' ' || *(cp + 1) == '\n' || *(cp + 1) == '\0')) {
322 while (isascii(*cp)) {
323 if (*cp == ' ' || *cp == '\n' || *cp == '\0')
326 p = strchr(base64url_table, *cp);
327 if (len > destsize || p == NULL || *cp == '\0') {
333 ac = (ac << 6) | (p - base64url_table);
337 *bp++ = (__u8)(ac >> bits);
342 if (!isascii(*cp) || (ac & ((1 << bits) - 1))) {
354 * gss_string_read() - read some string
356 * An empty string is represented with the single digit 0.
357 * String end is marked with a trailing space or '\n' or '\0'.
359 static inline int gss_string_read(char **src, char *dst, int destsize,
369 /* the single digit 0 is inserted if field is empty */
370 if (!allowzero && *cp == '0' &&
371 (*(cp + 1) == ' ' || *(cp + 1) == '\n')) {
376 while (isascii(*cp)) {
377 if (*cp == ' ' || *cp == '\n')
380 if (len >= destsize || *cp == '\0') {
402 * gss_u64_read() - read some u64
404 static inline int gss_u64_read_string(char **src, __u64 *n)
410 ret = gss_string_read(src, buf, sizeof(buf), 1);
415 *n = strtoull(buf, &ep, 0);
424 * gss_buffer_read() - read some buffer
426 static inline int gss_buffer_read(char **src, char *dst, int destsize)
438 if (len > destsize) {
446 /* read data itself */
448 while (size && destsize) {
453 if (!destsize && size)
463 * gss_buffer_get() - get reference to gss buffer
465 static inline int gss_buffer_get(char **src, __u32 *len, __u8 **data)
475 /* point to data buf */
489 * gss_u32_read() - read some u32
491 static inline int gss_u32_read(char **src, __u32 *val)