1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3 * linux/net/sunrpc/gss_krb5_mech.c
4 *
5 * Copyright (c) 2001-2008 The Regents of the University of Michigan.
6 * All rights reserved.
7 *
8 * Andy Adamson <andros@umich.edu>
9 * J. Bruce Fields <bfields@umich.edu>
10 */
11
12 #include <crypto/hash.h>
13 #include <crypto/skcipher.h>
14 #include <linux/err.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/types.h>
18 #include <linux/slab.h>
19 #include <linux/sunrpc/auth.h>
20 #include <linux/sunrpc/gss_krb5.h>
21 #include <linux/sunrpc/xdr.h>
22 #include <linux/sunrpc/gss_krb5_enctypes.h>
23
24 #include "auth_gss_internal.h"
25
26 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
27 # define RPCDBG_FACILITY RPCDBG_AUTH
28 #endif
29
30 static struct gss_api_mech gss_kerberos_mech;
31
32 static int gss_krb5_import_ctx_des(struct krb5_ctx *ctx, gfp_t gfp_mask);
33 static int gss_krb5_import_ctx_v1(struct krb5_ctx *ctx, gfp_t gfp_mask);
34 static int gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask);
35
36 static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
37 #ifndef CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES
38 /*
39 * DES (All DES enctypes are mapped to the same gss functionality)
40 */
41 {
42 .etype = ENCTYPE_DES_CBC_RAW,
43 .ctype = CKSUMTYPE_RSA_MD5,
44 .name = "des-cbc-crc",
45 .encrypt_name = "cbc(des)",
46 .cksum_name = "md5",
47 .encrypt = krb5_encrypt,
48 .decrypt = krb5_decrypt,
49 .import_ctx = gss_krb5_import_ctx_des,
50 .mk_key = NULL,
51 .signalg = SGN_ALG_DES_MAC_MD5,
52 .sealalg = SEAL_ALG_DES,
53 .keybytes = 7,
54 .keylength = 8,
55 .blocksize = 8,
56 .conflen = 8,
57 .cksumlength = 8,
58 .keyed_cksum = 0,
59 },
60 #endif /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */
61 /*
62 * 3DES
63 */
64 {
65 .etype = ENCTYPE_DES3_CBC_RAW,
66 .ctype = CKSUMTYPE_HMAC_SHA1_DES3,
67 .name = "des3-hmac-sha1",
68 .encrypt_name = "cbc(des3_ede)",
69 .cksum_name = "hmac(sha1)",
70 .encrypt = krb5_encrypt,
71 .decrypt = krb5_decrypt,
72 .import_ctx = gss_krb5_import_ctx_v1,
73 .mk_key = gss_krb5_des3_make_key,
74 .signalg = SGN_ALG_HMAC_SHA1_DES3_KD,
75 .sealalg = SEAL_ALG_DES3KD,
76 .keybytes = 21,
77 .keylength = 24,
78 .blocksize = 8,
79 .conflen = 8,
80 .cksumlength = 20,
81 .keyed_cksum = 1,
82 },
83 /*
84 * AES128
85 */
86 {
87 .etype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
88 .ctype = CKSUMTYPE_HMAC_SHA1_96_AES128,
89 .name = "aes128-cts",
90 .encrypt_name = "cts(cbc(aes))",
91 .cksum_name = "hmac(sha1)",
92 .encrypt = krb5_encrypt,
93 .decrypt = krb5_decrypt,
94 .import_ctx = gss_krb5_import_ctx_v2,
95 .mk_key = gss_krb5_aes_make_key,
96 .encrypt_v2 = gss_krb5_aes_encrypt,
97 .decrypt_v2 = gss_krb5_aes_decrypt,
98 .signalg = -1,
99 .sealalg = -1,
100 .keybytes = 16,
101 .keylength = 16,
102 .blocksize = 16,
103 .conflen = 16,
104 .cksumlength = 12,
105 .keyed_cksum = 1,
106 },
107 /*
108 * AES256
109 */
110 {
111 .etype = ENCTYPE_AES256_CTS_HMAC_SHA1_96,
112 .ctype = CKSUMTYPE_HMAC_SHA1_96_AES256,
113 .name = "aes256-cts",
114 .encrypt_name = "cts(cbc(aes))",
115 .cksum_name = "hmac(sha1)",
116 .encrypt = krb5_encrypt,
117 .decrypt = krb5_decrypt,
118 .import_ctx = gss_krb5_import_ctx_v2,
119 .mk_key = gss_krb5_aes_make_key,
120 .encrypt_v2 = gss_krb5_aes_encrypt,
121 .decrypt_v2 = gss_krb5_aes_decrypt,
122 .signalg = -1,
123 .sealalg = -1,
124 .keybytes = 32,
125 .keylength = 32,
126 .blocksize = 16,
127 .conflen = 16,
128 .cksumlength = 12,
129 .keyed_cksum = 1,
130 },
131 };
132
133 static const int num_supported_enctypes =
134 ARRAY_SIZE(supported_gss_krb5_enctypes);
135
136 static int
supported_gss_krb5_enctype(int etype)137 supported_gss_krb5_enctype(int etype)
138 {
139 int i;
140 for (i = 0; i < num_supported_enctypes; i++)
141 if (supported_gss_krb5_enctypes[i].etype == etype)
142 return 1;
143 return 0;
144 }
145
146 static const struct gss_krb5_enctype *
get_gss_krb5_enctype(int etype)147 get_gss_krb5_enctype(int etype)
148 {
149 int i;
150 for (i = 0; i < num_supported_enctypes; i++)
151 if (supported_gss_krb5_enctypes[i].etype == etype)
152 return &supported_gss_krb5_enctypes[i];
153 return NULL;
154 }
155
156 static inline const void *
get_key(const void *p, const void *end, struct krb5_ctx *ctx, struct crypto_sync_skcipher **res)157 get_key(const void *p, const void *end,
158 struct krb5_ctx *ctx, struct crypto_sync_skcipher **res)
159 {
160 struct xdr_netobj key;
161 int alg;
162
163 p = simple_get_bytes(p, end, &alg, sizeof(alg));
164 if (IS_ERR(p))
165 goto out_err;
166
167 switch (alg) {
168 case ENCTYPE_DES_CBC_CRC:
169 case ENCTYPE_DES_CBC_MD4:
170 case ENCTYPE_DES_CBC_MD5:
171 /* Map all these key types to ENCTYPE_DES_CBC_RAW */
172 alg = ENCTYPE_DES_CBC_RAW;
173 break;
174 }
175
176 if (!supported_gss_krb5_enctype(alg)) {
177 printk(KERN_WARNING "gss_kerberos_mech: unsupported "
178 "encryption key algorithm %d\n", alg);
179 p = ERR_PTR(-EINVAL);
180 goto out_err;
181 }
182 p = simple_get_netobj(p, end, &key);
183 if (IS_ERR(p))
184 goto out_err;
185
186 *res = crypto_alloc_sync_skcipher(ctx->gk5e->encrypt_name, 0, 0);
187 if (IS_ERR(*res)) {
188 printk(KERN_WARNING "gss_kerberos_mech: unable to initialize "
189 "crypto algorithm %s\n", ctx->gk5e->encrypt_name);
190 *res = NULL;
191 goto out_err_free_key;
192 }
193 if (crypto_sync_skcipher_setkey(*res, key.data, key.len)) {
194 printk(KERN_WARNING "gss_kerberos_mech: error setting key for "
195 "crypto algorithm %s\n", ctx->gk5e->encrypt_name);
196 goto out_err_free_tfm;
197 }
198
199 kfree(key.data);
200 return p;
201
202 out_err_free_tfm:
203 crypto_free_sync_skcipher(*res);
204 out_err_free_key:
205 kfree(key.data);
206 p = ERR_PTR(-EINVAL);
207 out_err:
208 return p;
209 }
210
211 static int
gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)212 gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
213 {
214 u32 seq_send;
215 int tmp;
216 u32 time32;
217
218 p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
219 if (IS_ERR(p))
220 goto out_err;
221
222 /* Old format supports only DES! Any other enctype uses new format */
223 ctx->enctype = ENCTYPE_DES_CBC_RAW;
224
225 ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
226 if (ctx->gk5e == NULL) {
227 p = ERR_PTR(-EINVAL);
228 goto out_err;
229 }
230
231 /* The downcall format was designed before we completely understood
232 * the uses of the context fields; so it includes some stuff we
233 * just give some minimal sanity-checking, and some we ignore
234 * completely (like the next twenty bytes): */
235 if (unlikely(p + 20 > end || p + 20 < p)) {
236 p = ERR_PTR(-EFAULT);
237 goto out_err;
238 }
239 p += 20;
240 p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
241 if (IS_ERR(p))
242 goto out_err;
243 if (tmp != SGN_ALG_DES_MAC_MD5) {
244 p = ERR_PTR(-ENOSYS);
245 goto out_err;
246 }
247 p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
248 if (IS_ERR(p))
249 goto out_err;
250 if (tmp != SEAL_ALG_DES) {
251 p = ERR_PTR(-ENOSYS);
252 goto out_err;
253 }
254 p = simple_get_bytes(p, end, &time32, sizeof(time32));
255 if (IS_ERR(p))
256 goto out_err;
257 /* unsigned 32-bit time overflows in year 2106 */
258 ctx->endtime = (time64_t)time32;
259 p = simple_get_bytes(p, end, &seq_send, sizeof(seq_send));
260 if (IS_ERR(p))
261 goto out_err;
262 atomic_set(&ctx->seq_send, seq_send);
263 p = simple_get_netobj(p, end, &ctx->mech_used);
264 if (IS_ERR(p))
265 goto out_err;
266 p = get_key(p, end, ctx, &ctx->enc);
267 if (IS_ERR(p))
268 goto out_err_free_mech;
269 p = get_key(p, end, ctx, &ctx->seq);
270 if (IS_ERR(p))
271 goto out_err_free_key1;
272 if (p != end) {
273 p = ERR_PTR(-EFAULT);
274 goto out_err_free_key2;
275 }
276
277 return 0;
278
279 out_err_free_key2:
280 crypto_free_sync_skcipher(ctx->seq);
281 out_err_free_key1:
282 crypto_free_sync_skcipher(ctx->enc);
283 out_err_free_mech:
284 kfree(ctx->mech_used.data);
285 out_err:
286 return PTR_ERR(p);
287 }
288
289 static struct crypto_sync_skcipher *
context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key)290 context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key)
291 {
292 struct crypto_sync_skcipher *cp;
293
294 cp = crypto_alloc_sync_skcipher(cname, 0, 0);
295 if (IS_ERR(cp)) {
296 dprintk("gss_kerberos_mech: unable to initialize "
297 "crypto algorithm %s\n", cname);
298 return NULL;
299 }
300 if (crypto_sync_skcipher_setkey(cp, key, ctx->gk5e->keylength)) {
301 dprintk("gss_kerberos_mech: error setting key for "
302 "crypto algorithm %s\n", cname);
303 crypto_free_sync_skcipher(cp);
304 return NULL;
305 }
306 return cp;
307 }
308
309 static inline void
set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed)310 set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed)
311 {
312 cdata[0] = (usage>>24)&0xff;
313 cdata[1] = (usage>>16)&0xff;
314 cdata[2] = (usage>>8)&0xff;
315 cdata[3] = usage&0xff;
316 cdata[4] = seed;
317 }
318
319 static int
gss_krb5_import_ctx_des(struct krb5_ctx *ctx, gfp_t gfp_mask)320 gss_krb5_import_ctx_des(struct krb5_ctx *ctx, gfp_t gfp_mask)
321 {
322 return -EINVAL;
323 }
324
325 static int
gss_krb5_import_ctx_v1(struct krb5_ctx *ctx, gfp_t gfp_mask)326 gss_krb5_import_ctx_v1(struct krb5_ctx *ctx, gfp_t gfp_mask)
327 {
328 struct xdr_netobj c, keyin, keyout;
329 u8 cdata[GSS_KRB5_K5CLENGTH];
330 u32 err;
331
332 c.len = GSS_KRB5_K5CLENGTH;
333 c.data = cdata;
334
335 keyin.data = ctx->Ksess;
336 keyin.len = ctx->gk5e->keylength;
337 keyout.len = ctx->gk5e->keylength;
338
339 /* seq uses the raw key */
340 ctx->seq = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,
341 ctx->Ksess);
342 if (ctx->seq == NULL)
343 goto out_err;
344
345 ctx->enc = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,
346 ctx->Ksess);
347 if (ctx->enc == NULL)
348 goto out_free_seq;
349
350 /* derive cksum */
351 set_cdata(cdata, KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM);
352 keyout.data = ctx->cksum;
353 err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
354 if (err) {
355 dprintk("%s: Error %d deriving cksum key\n",
356 __func__, err);
357 goto out_free_enc;
358 }
359
360 return 0;
361
362 out_free_enc:
363 crypto_free_sync_skcipher(ctx->enc);
364 out_free_seq:
365 crypto_free_sync_skcipher(ctx->seq);
366 out_err:
367 return -EINVAL;
368 }
369
370 static int
gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask)371 gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask)
372 {
373 struct xdr_netobj c, keyin, keyout;
374 u8 cdata[GSS_KRB5_K5CLENGTH];
375 u32 err;
376
377 c.len = GSS_KRB5_K5CLENGTH;
378 c.data = cdata;
379
380 keyin.data = ctx->Ksess;
381 keyin.len = ctx->gk5e->keylength;
382 keyout.len = ctx->gk5e->keylength;
383
384 /* initiator seal encryption */
385 set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
386 keyout.data = ctx->initiator_seal;
387 err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
388 if (err) {
389 dprintk("%s: Error %d deriving initiator_seal key\n",
390 __func__, err);
391 goto out_err;
392 }
393 ctx->initiator_enc = context_v2_alloc_cipher(ctx,
394 ctx->gk5e->encrypt_name,
395 ctx->initiator_seal);
396 if (ctx->initiator_enc == NULL)
397 goto out_err;
398
399 /* acceptor seal encryption */
400 set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
401 keyout.data = ctx->acceptor_seal;
402 err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
403 if (err) {
404 dprintk("%s: Error %d deriving acceptor_seal key\n",
405 __func__, err);
406 goto out_free_initiator_enc;
407 }
408 ctx->acceptor_enc = context_v2_alloc_cipher(ctx,
409 ctx->gk5e->encrypt_name,
410 ctx->acceptor_seal);
411 if (ctx->acceptor_enc == NULL)
412 goto out_free_initiator_enc;
413
414 /* initiator sign checksum */
415 set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
416 keyout.data = ctx->initiator_sign;
417 err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
418 if (err) {
419 dprintk("%s: Error %d deriving initiator_sign key\n",
420 __func__, err);
421 goto out_free_acceptor_enc;
422 }
423
424 /* acceptor sign checksum */
425 set_cdata(cdata, KG_USAGE_ACCEPTOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
426 keyout.data = ctx->acceptor_sign;
427 err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
428 if (err) {
429 dprintk("%s: Error %d deriving acceptor_sign key\n",
430 __func__, err);
431 goto out_free_acceptor_enc;
432 }
433
434 /* initiator seal integrity */
435 set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
436 keyout.data = ctx->initiator_integ;
437 err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
438 if (err) {
439 dprintk("%s: Error %d deriving initiator_integ key\n",
440 __func__, err);
441 goto out_free_acceptor_enc;
442 }
443
444 /* acceptor seal integrity */
445 set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
446 keyout.data = ctx->acceptor_integ;
447 err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
448 if (err) {
449 dprintk("%s: Error %d deriving acceptor_integ key\n",
450 __func__, err);
451 goto out_free_acceptor_enc;
452 }
453
454 switch (ctx->enctype) {
455 case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
456 case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
457 ctx->initiator_enc_aux =
458 context_v2_alloc_cipher(ctx, "cbc(aes)",
459 ctx->initiator_seal);
460 if (ctx->initiator_enc_aux == NULL)
461 goto out_free_acceptor_enc;
462 ctx->acceptor_enc_aux =
463 context_v2_alloc_cipher(ctx, "cbc(aes)",
464 ctx->acceptor_seal);
465 if (ctx->acceptor_enc_aux == NULL) {
466 crypto_free_sync_skcipher(ctx->initiator_enc_aux);
467 goto out_free_acceptor_enc;
468 }
469 }
470
471 return 0;
472
473 out_free_acceptor_enc:
474 crypto_free_sync_skcipher(ctx->acceptor_enc);
475 out_free_initiator_enc:
476 crypto_free_sync_skcipher(ctx->initiator_enc);
477 out_err:
478 return -EINVAL;
479 }
480
481 static int
gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, gfp_t gfp_mask)482 gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,
483 gfp_t gfp_mask)
484 {
485 u64 seq_send64;
486 int keylen;
487 u32 time32;
488 int ret;
489
490 p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));
491 if (IS_ERR(p))
492 goto out_err;
493 ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR;
494
495 p = simple_get_bytes(p, end, &time32, sizeof(time32));
496 if (IS_ERR(p))
497 goto out_err;
498 /* unsigned 32-bit time overflows in year 2106 */
499 ctx->endtime = (time64_t)time32;
500 p = simple_get_bytes(p, end, &seq_send64, sizeof(seq_send64));
501 if (IS_ERR(p))
502 goto out_err;
503 atomic64_set(&ctx->seq_send64, seq_send64);
504 /* set seq_send for use by "older" enctypes */
505 atomic_set(&ctx->seq_send, seq_send64);
506 if (seq_send64 != atomic_read(&ctx->seq_send)) {
507 dprintk("%s: seq_send64 %llx, seq_send %x overflow?\n", __func__,
508 seq_send64, atomic_read(&ctx->seq_send));
509 p = ERR_PTR(-EINVAL);
510 goto out_err;
511 }
512 p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
513 if (IS_ERR(p))
514 goto out_err;
515 /* Map ENCTYPE_DES3_CBC_SHA1 to ENCTYPE_DES3_CBC_RAW */
516 if (ctx->enctype == ENCTYPE_DES3_CBC_SHA1)
517 ctx->enctype = ENCTYPE_DES3_CBC_RAW;
518 ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
519 if (ctx->gk5e == NULL) {
520 dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
521 ctx->enctype);
522 p = ERR_PTR(-EINVAL);
523 goto out_err;
524 }
525 keylen = ctx->gk5e->keylength;
526
527 p = simple_get_bytes(p, end, ctx->Ksess, keylen);
528 if (IS_ERR(p))
529 goto out_err;
530
531 if (p != end) {
532 p = ERR_PTR(-EINVAL);
533 goto out_err;
534 }
535
536 ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data,
537 gss_kerberos_mech.gm_oid.len, gfp_mask);
538 if (unlikely(ctx->mech_used.data == NULL)) {
539 p = ERR_PTR(-ENOMEM);
540 goto out_err;
541 }
542 ctx->mech_used.len = gss_kerberos_mech.gm_oid.len;
543
544 ret = gss_krb5_import_ctx_v2(ctx, gfp_mask);
545 if (ret) {
546 p = ERR_PTR(ret);
547 goto out_free;
548 }
549
550 return 0;
551
552 out_free:
553 kfree(ctx->mech_used.data);
554 out_err:
555 return PTR_ERR(p);
556 }
557
558 static int
gss_import_sec_context_kerberos(const void *p, size_t len, struct gss_ctx *ctx_id, time64_t *endtime, gfp_t gfp_mask)559 gss_import_sec_context_kerberos(const void *p, size_t len,
560 struct gss_ctx *ctx_id,
561 time64_t *endtime,
562 gfp_t gfp_mask)
563 {
564 const void *end = (const void *)((const char *)p + len);
565 struct krb5_ctx *ctx;
566 int ret;
567
568 ctx = kzalloc(sizeof(*ctx), gfp_mask);
569 if (ctx == NULL)
570 return -ENOMEM;
571
572 if (len == 85)
573 ret = gss_import_v1_context(p, end, ctx);
574 else
575 ret = gss_import_v2_context(p, end, ctx, gfp_mask);
576
577 if (ret == 0) {
578 ctx_id->internal_ctx_id = ctx;
579 if (endtime)
580 *endtime = ctx->endtime;
581 } else
582 kfree(ctx);
583
584 dprintk("RPC: %s: returning %d\n", __func__, ret);
585 return ret;
586 }
587
588 static void
gss_delete_sec_context_kerberos(void *internal_ctx)589 gss_delete_sec_context_kerberos(void *internal_ctx) {
590 struct krb5_ctx *kctx = internal_ctx;
591
592 crypto_free_sync_skcipher(kctx->seq);
593 crypto_free_sync_skcipher(kctx->enc);
594 crypto_free_sync_skcipher(kctx->acceptor_enc);
595 crypto_free_sync_skcipher(kctx->initiator_enc);
596 crypto_free_sync_skcipher(kctx->acceptor_enc_aux);
597 crypto_free_sync_skcipher(kctx->initiator_enc_aux);
598 kfree(kctx->mech_used.data);
599 kfree(kctx);
600 }
601
602 static const struct gss_api_ops gss_kerberos_ops = {
603 .gss_import_sec_context = gss_import_sec_context_kerberos,
604 .gss_get_mic = gss_get_mic_kerberos,
605 .gss_verify_mic = gss_verify_mic_kerberos,
606 .gss_wrap = gss_wrap_kerberos,
607 .gss_unwrap = gss_unwrap_kerberos,
608 .gss_delete_sec_context = gss_delete_sec_context_kerberos,
609 };
610
611 static struct pf_desc gss_kerberos_pfs[] = {
612 [0] = {
613 .pseudoflavor = RPC_AUTH_GSS_KRB5,
614 .qop = GSS_C_QOP_DEFAULT,
615 .service = RPC_GSS_SVC_NONE,
616 .name = "krb5",
617 },
618 [1] = {
619 .pseudoflavor = RPC_AUTH_GSS_KRB5I,
620 .qop = GSS_C_QOP_DEFAULT,
621 .service = RPC_GSS_SVC_INTEGRITY,
622 .name = "krb5i",
623 .datatouch = true,
624 },
625 [2] = {
626 .pseudoflavor = RPC_AUTH_GSS_KRB5P,
627 .qop = GSS_C_QOP_DEFAULT,
628 .service = RPC_GSS_SVC_PRIVACY,
629 .name = "krb5p",
630 .datatouch = true,
631 },
632 };
633
634 MODULE_ALIAS("rpc-auth-gss-krb5");
635 MODULE_ALIAS("rpc-auth-gss-krb5i");
636 MODULE_ALIAS("rpc-auth-gss-krb5p");
637 MODULE_ALIAS("rpc-auth-gss-390003");
638 MODULE_ALIAS("rpc-auth-gss-390004");
639 MODULE_ALIAS("rpc-auth-gss-390005");
640 MODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2");
641
642 static struct gss_api_mech gss_kerberos_mech = {
643 .gm_name = "krb5",
644 .gm_owner = THIS_MODULE,
645 .gm_oid = { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" },
646 .gm_ops = &gss_kerberos_ops,
647 .gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs),
648 .gm_pfs = gss_kerberos_pfs,
649 .gm_upcall_enctypes = KRB5_SUPPORTED_ENCTYPES,
650 };
651
init_kerberos_module(void)652 static int __init init_kerberos_module(void)
653 {
654 int status;
655
656 status = gss_mech_register(&gss_kerberos_mech);
657 if (status)
658 printk("Failed to register kerberos gss mechanism!\n");
659 return status;
660 }
661
cleanup_kerberos_module(void)662 static void __exit cleanup_kerberos_module(void)
663 {
664 gss_mech_unregister(&gss_kerberos_mech);
665 }
666
667 MODULE_LICENSE("GPL");
668 module_init(init_kerberos_module);
669 module_exit(cleanup_kerberos_module);
670