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