1 // SPDX-License-Identifier: BSD-3-Clause
3 * linux/net/sunrpc/gss_krb5_mech.c
5 * Copyright (c) 2001-2008 The Regents of the University of Michigan.
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
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)",
41 .encrypt
= krb5_encrypt
,
42 .decrypt
= krb5_decrypt
,
44 .signalg
= SGN_ALG_DES_MAC_MD5
,
45 .sealalg
= SEAL_ALG_DES
,
53 #endif /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */
58 .etype
= ENCTYPE_ARCFOUR_HMAC
,
59 .ctype
= CKSUMTYPE_HMAC_MD5_ARCFOUR
,
61 .encrypt_name
= "ecb(arc4)",
62 .cksum_name
= "hmac(md5)",
63 .encrypt
= krb5_encrypt
,
64 .decrypt
= krb5_decrypt
,
66 .signalg
= SGN_ALG_HMAC_MD5
,
67 .sealalg
= SEAL_ALG_MICROSOFT_RC4
,
79 .etype
= ENCTYPE_DES3_CBC_RAW
,
80 .ctype
= CKSUMTYPE_HMAC_SHA1_DES3
,
81 .name
= "des3-hmac-sha1",
82 .encrypt_name
= "cbc(des3_ede)",
83 .cksum_name
= "hmac(sha1)",
84 .encrypt
= krb5_encrypt
,
85 .decrypt
= krb5_decrypt
,
86 .mk_key
= gss_krb5_des3_make_key
,
87 .signalg
= SGN_ALG_HMAC_SHA1_DES3_KD
,
88 .sealalg
= SEAL_ALG_DES3KD
,
100 .etype
= ENCTYPE_AES128_CTS_HMAC_SHA1_96
,
101 .ctype
= CKSUMTYPE_HMAC_SHA1_96_AES128
,
102 .name
= "aes128-cts",
103 .encrypt_name
= "cts(cbc(aes))",
104 .cksum_name
= "hmac(sha1)",
105 .encrypt
= krb5_encrypt
,
106 .decrypt
= krb5_decrypt
,
107 .mk_key
= gss_krb5_aes_make_key
,
108 .encrypt_v2
= gss_krb5_aes_encrypt
,
109 .decrypt_v2
= gss_krb5_aes_decrypt
,
123 .etype
= ENCTYPE_AES256_CTS_HMAC_SHA1_96
,
124 .ctype
= CKSUMTYPE_HMAC_SHA1_96_AES256
,
125 .name
= "aes256-cts",
126 .encrypt_name
= "cts(cbc(aes))",
127 .cksum_name
= "hmac(sha1)",
128 .encrypt
= krb5_encrypt
,
129 .decrypt
= krb5_decrypt
,
130 .mk_key
= gss_krb5_aes_make_key
,
131 .encrypt_v2
= gss_krb5_aes_encrypt
,
132 .decrypt_v2
= gss_krb5_aes_decrypt
,
144 static const int num_supported_enctypes
=
145 ARRAY_SIZE(supported_gss_krb5_enctypes
);
148 supported_gss_krb5_enctype(int etype
)
151 for (i
= 0; i
< num_supported_enctypes
; i
++)
152 if (supported_gss_krb5_enctypes
[i
].etype
== etype
)
157 static const struct gss_krb5_enctype
*
158 get_gss_krb5_enctype(int etype
)
161 for (i
= 0; i
< num_supported_enctypes
; i
++)
162 if (supported_gss_krb5_enctypes
[i
].etype
== etype
)
163 return &supported_gss_krb5_enctypes
[i
];
168 simple_get_bytes(const void *p
, const void *end
, void *res
, int len
)
170 const void *q
= (const void *)((const char *)p
+ len
);
171 if (unlikely(q
> end
|| q
< p
))
172 return ERR_PTR(-EFAULT
);
178 simple_get_netobj(const void *p
, const void *end
, struct xdr_netobj
*res
)
183 p
= simple_get_bytes(p
, end
, &len
, sizeof(len
));
186 q
= (const void *)((const char *)p
+ len
);
187 if (unlikely(q
> end
|| q
< p
))
188 return ERR_PTR(-EFAULT
);
189 res
->data
= kmemdup(p
, len
, GFP_NOFS
);
190 if (unlikely(res
->data
== NULL
))
191 return ERR_PTR(-ENOMEM
);
196 static inline const void *
197 get_key(const void *p
, const void *end
,
198 struct krb5_ctx
*ctx
, struct crypto_sync_skcipher
**res
)
200 struct xdr_netobj key
;
203 p
= simple_get_bytes(p
, end
, &alg
, sizeof(alg
));
208 case ENCTYPE_DES_CBC_CRC
:
209 case ENCTYPE_DES_CBC_MD4
:
210 case ENCTYPE_DES_CBC_MD5
:
211 /* Map all these key types to ENCTYPE_DES_CBC_RAW */
212 alg
= ENCTYPE_DES_CBC_RAW
;
216 if (!supported_gss_krb5_enctype(alg
)) {
217 printk(KERN_WARNING
"gss_kerberos_mech: unsupported "
218 "encryption key algorithm %d\n", alg
);
219 p
= ERR_PTR(-EINVAL
);
222 p
= simple_get_netobj(p
, end
, &key
);
226 *res
= crypto_alloc_sync_skcipher(ctx
->gk5e
->encrypt_name
, 0, 0);
228 printk(KERN_WARNING
"gss_kerberos_mech: unable to initialize "
229 "crypto algorithm %s\n", ctx
->gk5e
->encrypt_name
);
231 goto out_err_free_key
;
233 if (crypto_sync_skcipher_setkey(*res
, key
.data
, key
.len
)) {
234 printk(KERN_WARNING
"gss_kerberos_mech: error setting key for "
235 "crypto algorithm %s\n", ctx
->gk5e
->encrypt_name
);
236 goto out_err_free_tfm
;
243 crypto_free_sync_skcipher(*res
);
246 p
= ERR_PTR(-EINVAL
);
252 gss_import_v1_context(const void *p
, const void *end
, struct krb5_ctx
*ctx
)
258 p
= simple_get_bytes(p
, end
, &ctx
->initiate
, sizeof(ctx
->initiate
));
262 /* Old format supports only DES! Any other enctype uses new format */
263 ctx
->enctype
= ENCTYPE_DES_CBC_RAW
;
265 ctx
->gk5e
= get_gss_krb5_enctype(ctx
->enctype
);
266 if (ctx
->gk5e
== NULL
) {
267 p
= ERR_PTR(-EINVAL
);
271 /* The downcall format was designed before we completely understood
272 * the uses of the context fields; so it includes some stuff we
273 * just give some minimal sanity-checking, and some we ignore
274 * completely (like the next twenty bytes): */
275 if (unlikely(p
+ 20 > end
|| p
+ 20 < p
)) {
276 p
= ERR_PTR(-EFAULT
);
280 p
= simple_get_bytes(p
, end
, &tmp
, sizeof(tmp
));
283 if (tmp
!= SGN_ALG_DES_MAC_MD5
) {
284 p
= ERR_PTR(-ENOSYS
);
287 p
= simple_get_bytes(p
, end
, &tmp
, sizeof(tmp
));
290 if (tmp
!= SEAL_ALG_DES
) {
291 p
= ERR_PTR(-ENOSYS
);
294 p
= simple_get_bytes(p
, end
, &time32
, sizeof(time32
));
297 /* unsigned 32-bit time overflows in year 2106 */
298 ctx
->endtime
= (time64_t
)time32
;
299 p
= simple_get_bytes(p
, end
, &seq_send
, sizeof(seq_send
));
302 atomic_set(&ctx
->seq_send
, seq_send
);
303 p
= simple_get_netobj(p
, end
, &ctx
->mech_used
);
306 p
= get_key(p
, end
, ctx
, &ctx
->enc
);
308 goto out_err_free_mech
;
309 p
= get_key(p
, end
, ctx
, &ctx
->seq
);
311 goto out_err_free_key1
;
313 p
= ERR_PTR(-EFAULT
);
314 goto out_err_free_key2
;
320 crypto_free_sync_skcipher(ctx
->seq
);
322 crypto_free_sync_skcipher(ctx
->enc
);
324 kfree(ctx
->mech_used
.data
);
329 static struct crypto_sync_skcipher
*
330 context_v2_alloc_cipher(struct krb5_ctx
*ctx
, const char *cname
, u8
*key
)
332 struct crypto_sync_skcipher
*cp
;
334 cp
= crypto_alloc_sync_skcipher(cname
, 0, 0);
336 dprintk("gss_kerberos_mech: unable to initialize "
337 "crypto algorithm %s\n", cname
);
340 if (crypto_sync_skcipher_setkey(cp
, key
, ctx
->gk5e
->keylength
)) {
341 dprintk("gss_kerberos_mech: error setting key for "
342 "crypto algorithm %s\n", cname
);
343 crypto_free_sync_skcipher(cp
);
350 set_cdata(u8 cdata
[GSS_KRB5_K5CLENGTH
], u32 usage
, u8 seed
)
352 cdata
[0] = (usage
>>24)&0xff;
353 cdata
[1] = (usage
>>16)&0xff;
354 cdata
[2] = (usage
>>8)&0xff;
355 cdata
[3] = usage
&0xff;
360 context_derive_keys_des3(struct krb5_ctx
*ctx
, gfp_t gfp_mask
)
362 struct xdr_netobj c
, keyin
, keyout
;
363 u8 cdata
[GSS_KRB5_K5CLENGTH
];
366 c
.len
= GSS_KRB5_K5CLENGTH
;
369 keyin
.data
= ctx
->Ksess
;
370 keyin
.len
= ctx
->gk5e
->keylength
;
371 keyout
.len
= ctx
->gk5e
->keylength
;
373 /* seq uses the raw key */
374 ctx
->seq
= context_v2_alloc_cipher(ctx
, ctx
->gk5e
->encrypt_name
,
376 if (ctx
->seq
== NULL
)
379 ctx
->enc
= context_v2_alloc_cipher(ctx
, ctx
->gk5e
->encrypt_name
,
381 if (ctx
->enc
== NULL
)
385 set_cdata(cdata
, KG_USAGE_SIGN
, KEY_USAGE_SEED_CHECKSUM
);
386 keyout
.data
= ctx
->cksum
;
387 err
= krb5_derive_key(ctx
->gk5e
, &keyin
, &keyout
, &c
, gfp_mask
);
389 dprintk("%s: Error %d deriving cksum key\n",
397 crypto_free_sync_skcipher(ctx
->enc
);
399 crypto_free_sync_skcipher(ctx
->seq
);
405 * Note that RC4 depends on deriving keys using the sequence
406 * number or the checksum of a token. Therefore, the final keys
407 * cannot be calculated until the token is being constructed!
410 context_derive_keys_rc4(struct krb5_ctx
*ctx
)
412 struct crypto_shash
*hmac
;
413 char sigkeyconstant
[] = "signaturekey";
414 int slen
= strlen(sigkeyconstant
) + 1; /* include null terminator */
415 struct shash_desc
*desc
;
418 dprintk("RPC: %s: entered\n", __func__
);
420 * derive cksum (aka Ksign) key
422 hmac
= crypto_alloc_shash(ctx
->gk5e
->cksum_name
, 0, 0);
424 dprintk("%s: error %ld allocating hash '%s'\n",
425 __func__
, PTR_ERR(hmac
), ctx
->gk5e
->cksum_name
);
430 err
= crypto_shash_setkey(hmac
, ctx
->Ksess
, ctx
->gk5e
->keylength
);
432 goto out_err_free_hmac
;
435 desc
= kmalloc(sizeof(*desc
) + crypto_shash_descsize(hmac
), GFP_NOFS
);
437 dprintk("%s: failed to allocate hash descriptor for '%s'\n",
438 __func__
, ctx
->gk5e
->cksum_name
);
440 goto out_err_free_hmac
;
445 err
= crypto_shash_digest(desc
, sigkeyconstant
, slen
, ctx
->cksum
);
448 goto out_err_free_hmac
;
450 * allocate hash, and skciphers for data and seqnum encryption
452 ctx
->enc
= crypto_alloc_sync_skcipher(ctx
->gk5e
->encrypt_name
, 0, 0);
453 if (IS_ERR(ctx
->enc
)) {
454 err
= PTR_ERR(ctx
->enc
);
455 goto out_err_free_hmac
;
458 ctx
->seq
= crypto_alloc_sync_skcipher(ctx
->gk5e
->encrypt_name
, 0, 0);
459 if (IS_ERR(ctx
->seq
)) {
460 crypto_free_sync_skcipher(ctx
->enc
);
461 err
= PTR_ERR(ctx
->seq
);
462 goto out_err_free_hmac
;
465 dprintk("RPC: %s: returning success\n", __func__
);
470 crypto_free_shash(hmac
);
472 dprintk("RPC: %s: returning %d\n", __func__
, err
);
477 context_derive_keys_new(struct krb5_ctx
*ctx
, gfp_t gfp_mask
)
479 struct xdr_netobj c
, keyin
, keyout
;
480 u8 cdata
[GSS_KRB5_K5CLENGTH
];
483 c
.len
= GSS_KRB5_K5CLENGTH
;
486 keyin
.data
= ctx
->Ksess
;
487 keyin
.len
= ctx
->gk5e
->keylength
;
488 keyout
.len
= ctx
->gk5e
->keylength
;
490 /* initiator seal encryption */
491 set_cdata(cdata
, KG_USAGE_INITIATOR_SEAL
, KEY_USAGE_SEED_ENCRYPTION
);
492 keyout
.data
= ctx
->initiator_seal
;
493 err
= krb5_derive_key(ctx
->gk5e
, &keyin
, &keyout
, &c
, gfp_mask
);
495 dprintk("%s: Error %d deriving initiator_seal key\n",
499 ctx
->initiator_enc
= context_v2_alloc_cipher(ctx
,
500 ctx
->gk5e
->encrypt_name
,
501 ctx
->initiator_seal
);
502 if (ctx
->initiator_enc
== NULL
)
505 /* acceptor seal encryption */
506 set_cdata(cdata
, KG_USAGE_ACCEPTOR_SEAL
, KEY_USAGE_SEED_ENCRYPTION
);
507 keyout
.data
= ctx
->acceptor_seal
;
508 err
= krb5_derive_key(ctx
->gk5e
, &keyin
, &keyout
, &c
, gfp_mask
);
510 dprintk("%s: Error %d deriving acceptor_seal key\n",
512 goto out_free_initiator_enc
;
514 ctx
->acceptor_enc
= context_v2_alloc_cipher(ctx
,
515 ctx
->gk5e
->encrypt_name
,
517 if (ctx
->acceptor_enc
== NULL
)
518 goto out_free_initiator_enc
;
520 /* initiator sign checksum */
521 set_cdata(cdata
, KG_USAGE_INITIATOR_SIGN
, KEY_USAGE_SEED_CHECKSUM
);
522 keyout
.data
= ctx
->initiator_sign
;
523 err
= krb5_derive_key(ctx
->gk5e
, &keyin
, &keyout
, &c
, gfp_mask
);
525 dprintk("%s: Error %d deriving initiator_sign key\n",
527 goto out_free_acceptor_enc
;
530 /* acceptor sign checksum */
531 set_cdata(cdata
, KG_USAGE_ACCEPTOR_SIGN
, KEY_USAGE_SEED_CHECKSUM
);
532 keyout
.data
= ctx
->acceptor_sign
;
533 err
= krb5_derive_key(ctx
->gk5e
, &keyin
, &keyout
, &c
, gfp_mask
);
535 dprintk("%s: Error %d deriving acceptor_sign key\n",
537 goto out_free_acceptor_enc
;
540 /* initiator seal integrity */
541 set_cdata(cdata
, KG_USAGE_INITIATOR_SEAL
, KEY_USAGE_SEED_INTEGRITY
);
542 keyout
.data
= ctx
->initiator_integ
;
543 err
= krb5_derive_key(ctx
->gk5e
, &keyin
, &keyout
, &c
, gfp_mask
);
545 dprintk("%s: Error %d deriving initiator_integ key\n",
547 goto out_free_acceptor_enc
;
550 /* acceptor seal integrity */
551 set_cdata(cdata
, KG_USAGE_ACCEPTOR_SEAL
, KEY_USAGE_SEED_INTEGRITY
);
552 keyout
.data
= ctx
->acceptor_integ
;
553 err
= krb5_derive_key(ctx
->gk5e
, &keyin
, &keyout
, &c
, gfp_mask
);
555 dprintk("%s: Error %d deriving acceptor_integ key\n",
557 goto out_free_acceptor_enc
;
560 switch (ctx
->enctype
) {
561 case ENCTYPE_AES128_CTS_HMAC_SHA1_96
:
562 case ENCTYPE_AES256_CTS_HMAC_SHA1_96
:
563 ctx
->initiator_enc_aux
=
564 context_v2_alloc_cipher(ctx
, "cbc(aes)",
565 ctx
->initiator_seal
);
566 if (ctx
->initiator_enc_aux
== NULL
)
567 goto out_free_acceptor_enc
;
568 ctx
->acceptor_enc_aux
=
569 context_v2_alloc_cipher(ctx
, "cbc(aes)",
571 if (ctx
->acceptor_enc_aux
== NULL
) {
572 crypto_free_sync_skcipher(ctx
->initiator_enc_aux
);
573 goto out_free_acceptor_enc
;
579 out_free_acceptor_enc
:
580 crypto_free_sync_skcipher(ctx
->acceptor_enc
);
581 out_free_initiator_enc
:
582 crypto_free_sync_skcipher(ctx
->initiator_enc
);
588 gss_import_v2_context(const void *p
, const void *end
, struct krb5_ctx
*ctx
,
595 p
= simple_get_bytes(p
, end
, &ctx
->flags
, sizeof(ctx
->flags
));
598 ctx
->initiate
= ctx
->flags
& KRB5_CTX_FLAG_INITIATOR
;
600 p
= simple_get_bytes(p
, end
, &time32
, sizeof(time32
));
603 /* unsigned 32-bit time overflows in year 2106 */
604 ctx
->endtime
= (time64_t
)time32
;
605 p
= simple_get_bytes(p
, end
, &seq_send64
, sizeof(seq_send64
));
608 atomic64_set(&ctx
->seq_send64
, seq_send64
);
609 /* set seq_send for use by "older" enctypes */
610 atomic_set(&ctx
->seq_send
, seq_send64
);
611 if (seq_send64
!= atomic_read(&ctx
->seq_send
)) {
612 dprintk("%s: seq_send64 %llx, seq_send %x overflow?\n", __func__
,
613 seq_send64
, atomic_read(&ctx
->seq_send
));
614 p
= ERR_PTR(-EINVAL
);
617 p
= simple_get_bytes(p
, end
, &ctx
->enctype
, sizeof(ctx
->enctype
));
620 /* Map ENCTYPE_DES3_CBC_SHA1 to ENCTYPE_DES3_CBC_RAW */
621 if (ctx
->enctype
== ENCTYPE_DES3_CBC_SHA1
)
622 ctx
->enctype
= ENCTYPE_DES3_CBC_RAW
;
623 ctx
->gk5e
= get_gss_krb5_enctype(ctx
->enctype
);
624 if (ctx
->gk5e
== NULL
) {
625 dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
627 p
= ERR_PTR(-EINVAL
);
630 keylen
= ctx
->gk5e
->keylength
;
632 p
= simple_get_bytes(p
, end
, ctx
->Ksess
, keylen
);
637 p
= ERR_PTR(-EINVAL
);
641 ctx
->mech_used
.data
= kmemdup(gss_kerberos_mech
.gm_oid
.data
,
642 gss_kerberos_mech
.gm_oid
.len
, gfp_mask
);
643 if (unlikely(ctx
->mech_used
.data
== NULL
)) {
644 p
= ERR_PTR(-ENOMEM
);
647 ctx
->mech_used
.len
= gss_kerberos_mech
.gm_oid
.len
;
649 switch (ctx
->enctype
) {
650 case ENCTYPE_DES3_CBC_RAW
:
651 return context_derive_keys_des3(ctx
, gfp_mask
);
652 case ENCTYPE_ARCFOUR_HMAC
:
653 return context_derive_keys_rc4(ctx
);
654 case ENCTYPE_AES128_CTS_HMAC_SHA1_96
:
655 case ENCTYPE_AES256_CTS_HMAC_SHA1_96
:
656 return context_derive_keys_new(ctx
, gfp_mask
);
666 gss_import_sec_context_kerberos(const void *p
, size_t len
,
667 struct gss_ctx
*ctx_id
,
671 const void *end
= (const void *)((const char *)p
+ len
);
672 struct krb5_ctx
*ctx
;
675 ctx
= kzalloc(sizeof(*ctx
), gfp_mask
);
680 ret
= gss_import_v1_context(p
, end
, ctx
);
682 ret
= gss_import_v2_context(p
, end
, ctx
, gfp_mask
);
685 ctx_id
->internal_ctx_id
= ctx
;
687 *endtime
= ctx
->endtime
;
691 dprintk("RPC: %s: returning %d\n", __func__
, ret
);
696 gss_delete_sec_context_kerberos(void *internal_ctx
) {
697 struct krb5_ctx
*kctx
= internal_ctx
;
699 crypto_free_sync_skcipher(kctx
->seq
);
700 crypto_free_sync_skcipher(kctx
->enc
);
701 crypto_free_sync_skcipher(kctx
->acceptor_enc
);
702 crypto_free_sync_skcipher(kctx
->initiator_enc
);
703 crypto_free_sync_skcipher(kctx
->acceptor_enc_aux
);
704 crypto_free_sync_skcipher(kctx
->initiator_enc_aux
);
705 kfree(kctx
->mech_used
.data
);
709 static const struct gss_api_ops gss_kerberos_ops
= {
710 .gss_import_sec_context
= gss_import_sec_context_kerberos
,
711 .gss_get_mic
= gss_get_mic_kerberos
,
712 .gss_verify_mic
= gss_verify_mic_kerberos
,
713 .gss_wrap
= gss_wrap_kerberos
,
714 .gss_unwrap
= gss_unwrap_kerberos
,
715 .gss_delete_sec_context
= gss_delete_sec_context_kerberos
,
718 static struct pf_desc gss_kerberos_pfs
[] = {
720 .pseudoflavor
= RPC_AUTH_GSS_KRB5
,
721 .qop
= GSS_C_QOP_DEFAULT
,
722 .service
= RPC_GSS_SVC_NONE
,
726 .pseudoflavor
= RPC_AUTH_GSS_KRB5I
,
727 .qop
= GSS_C_QOP_DEFAULT
,
728 .service
= RPC_GSS_SVC_INTEGRITY
,
733 .pseudoflavor
= RPC_AUTH_GSS_KRB5P
,
734 .qop
= GSS_C_QOP_DEFAULT
,
735 .service
= RPC_GSS_SVC_PRIVACY
,
741 MODULE_ALIAS("rpc-auth-gss-krb5");
742 MODULE_ALIAS("rpc-auth-gss-krb5i");
743 MODULE_ALIAS("rpc-auth-gss-krb5p");
744 MODULE_ALIAS("rpc-auth-gss-390003");
745 MODULE_ALIAS("rpc-auth-gss-390004");
746 MODULE_ALIAS("rpc-auth-gss-390005");
747 MODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2");
749 static struct gss_api_mech gss_kerberos_mech
= {
751 .gm_owner
= THIS_MODULE
,
752 .gm_oid
= { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" },
753 .gm_ops
= &gss_kerberos_ops
,
754 .gm_pf_num
= ARRAY_SIZE(gss_kerberos_pfs
),
755 .gm_pfs
= gss_kerberos_pfs
,
756 .gm_upcall_enctypes
= KRB5_SUPPORTED_ENCTYPES
,
759 static int __init
init_kerberos_module(void)
763 status
= gss_mech_register(&gss_kerberos_mech
);
765 printk("Failed to register kerberos gss mechanism!\n");
769 static void __exit
cleanup_kerberos_module(void)
771 gss_mech_unregister(&gss_kerberos_mech
);
774 MODULE_LICENSE("GPL");
775 module_init(init_kerberos_module
);
776 module_exit(cleanup_kerberos_module
);