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 <kunit/visibility.h>
24 #include "auth_gss_internal.h"
25 #include "gss_krb5_internal.h"
27 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
28 # define RPCDBG_FACILITY RPCDBG_AUTH
31 static struct gss_api_mech gss_kerberos_mech
;
33 static const struct gss_krb5_enctype supported_gss_krb5_enctypes
[] = {
34 #if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1)
36 * AES-128 with SHA-1 (RFC 3962)
39 .etype
= ENCTYPE_AES128_CTS_HMAC_SHA1_96
,
40 .ctype
= CKSUMTYPE_HMAC_SHA1_96_AES128
,
42 .encrypt_name
= "cts(cbc(aes))",
43 .aux_cipher
= "cbc(aes)",
44 .cksum_name
= "hmac(sha1)",
45 .derive_key
= krb5_derive_key_v2
,
46 .encrypt
= gss_krb5_aes_encrypt
,
47 .decrypt
= gss_krb5_aes_decrypt
,
49 .get_mic
= gss_krb5_get_mic_v2
,
50 .verify_mic
= gss_krb5_verify_mic_v2
,
51 .wrap
= gss_krb5_wrap_v2
,
52 .unwrap
= gss_krb5_unwrap_v2
,
57 .keylength
= BITS2OCTETS(128),
58 .Kc_length
= BITS2OCTETS(128),
59 .Ke_length
= BITS2OCTETS(128),
60 .Ki_length
= BITS2OCTETS(128),
61 .cksumlength
= BITS2OCTETS(96),
65 * AES-256 with SHA-1 (RFC 3962)
68 .etype
= ENCTYPE_AES256_CTS_HMAC_SHA1_96
,
69 .ctype
= CKSUMTYPE_HMAC_SHA1_96_AES256
,
71 .encrypt_name
= "cts(cbc(aes))",
72 .aux_cipher
= "cbc(aes)",
73 .cksum_name
= "hmac(sha1)",
74 .derive_key
= krb5_derive_key_v2
,
75 .encrypt
= gss_krb5_aes_encrypt
,
76 .decrypt
= gss_krb5_aes_decrypt
,
78 .get_mic
= gss_krb5_get_mic_v2
,
79 .verify_mic
= gss_krb5_verify_mic_v2
,
80 .wrap
= gss_krb5_wrap_v2
,
81 .unwrap
= gss_krb5_unwrap_v2
,
86 .keylength
= BITS2OCTETS(256),
87 .Kc_length
= BITS2OCTETS(256),
88 .Ke_length
= BITS2OCTETS(256),
89 .Ki_length
= BITS2OCTETS(256),
90 .cksumlength
= BITS2OCTETS(96),
95 #if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA)
97 * Camellia-128 with CMAC (RFC 6803)
100 .etype
= ENCTYPE_CAMELLIA128_CTS_CMAC
,
101 .ctype
= CKSUMTYPE_CMAC_CAMELLIA128
,
102 .name
= "camellia128-cts-cmac",
103 .encrypt_name
= "cts(cbc(camellia))",
104 .aux_cipher
= "cbc(camellia)",
105 .cksum_name
= "cmac(camellia)",
106 .cksumlength
= BITS2OCTETS(128),
108 .keylength
= BITS2OCTETS(128),
109 .Kc_length
= BITS2OCTETS(128),
110 .Ke_length
= BITS2OCTETS(128),
111 .Ki_length
= BITS2OCTETS(128),
113 .derive_key
= krb5_kdf_feedback_cmac
,
114 .encrypt
= gss_krb5_aes_encrypt
,
115 .decrypt
= gss_krb5_aes_decrypt
,
117 .get_mic
= gss_krb5_get_mic_v2
,
118 .verify_mic
= gss_krb5_verify_mic_v2
,
119 .wrap
= gss_krb5_wrap_v2
,
120 .unwrap
= gss_krb5_unwrap_v2
,
123 * Camellia-256 with CMAC (RFC 6803)
126 .etype
= ENCTYPE_CAMELLIA256_CTS_CMAC
,
127 .ctype
= CKSUMTYPE_CMAC_CAMELLIA256
,
128 .name
= "camellia256-cts-cmac",
129 .encrypt_name
= "cts(cbc(camellia))",
130 .aux_cipher
= "cbc(camellia)",
131 .cksum_name
= "cmac(camellia)",
132 .cksumlength
= BITS2OCTETS(128),
134 .keylength
= BITS2OCTETS(256),
135 .Kc_length
= BITS2OCTETS(256),
136 .Ke_length
= BITS2OCTETS(256),
137 .Ki_length
= BITS2OCTETS(256),
139 .derive_key
= krb5_kdf_feedback_cmac
,
140 .encrypt
= gss_krb5_aes_encrypt
,
141 .decrypt
= gss_krb5_aes_decrypt
,
143 .get_mic
= gss_krb5_get_mic_v2
,
144 .verify_mic
= gss_krb5_verify_mic_v2
,
145 .wrap
= gss_krb5_wrap_v2
,
146 .unwrap
= gss_krb5_unwrap_v2
,
150 #if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2)
152 * AES-128 with SHA-256 (RFC 8009)
155 .etype
= ENCTYPE_AES128_CTS_HMAC_SHA256_128
,
156 .ctype
= CKSUMTYPE_HMAC_SHA256_128_AES128
,
157 .name
= "aes128-cts-hmac-sha256-128",
158 .encrypt_name
= "cts(cbc(aes))",
159 .aux_cipher
= "cbc(aes)",
160 .cksum_name
= "hmac(sha256)",
161 .cksumlength
= BITS2OCTETS(128),
163 .keylength
= BITS2OCTETS(128),
164 .Kc_length
= BITS2OCTETS(128),
165 .Ke_length
= BITS2OCTETS(128),
166 .Ki_length
= BITS2OCTETS(128),
168 .derive_key
= krb5_kdf_hmac_sha2
,
169 .encrypt
= krb5_etm_encrypt
,
170 .decrypt
= krb5_etm_decrypt
,
172 .get_mic
= gss_krb5_get_mic_v2
,
173 .verify_mic
= gss_krb5_verify_mic_v2
,
174 .wrap
= gss_krb5_wrap_v2
,
175 .unwrap
= gss_krb5_unwrap_v2
,
178 * AES-256 with SHA-384 (RFC 8009)
181 .etype
= ENCTYPE_AES256_CTS_HMAC_SHA384_192
,
182 .ctype
= CKSUMTYPE_HMAC_SHA384_192_AES256
,
183 .name
= "aes256-cts-hmac-sha384-192",
184 .encrypt_name
= "cts(cbc(aes))",
185 .aux_cipher
= "cbc(aes)",
186 .cksum_name
= "hmac(sha384)",
187 .cksumlength
= BITS2OCTETS(192),
189 .keylength
= BITS2OCTETS(256),
190 .Kc_length
= BITS2OCTETS(192),
191 .Ke_length
= BITS2OCTETS(256),
192 .Ki_length
= BITS2OCTETS(192),
194 .derive_key
= krb5_kdf_hmac_sha2
,
195 .encrypt
= krb5_etm_encrypt
,
196 .decrypt
= krb5_etm_decrypt
,
198 .get_mic
= gss_krb5_get_mic_v2
,
199 .verify_mic
= gss_krb5_verify_mic_v2
,
200 .wrap
= gss_krb5_wrap_v2
,
201 .unwrap
= gss_krb5_unwrap_v2
,
207 * The list of advertised enctypes is specified in order of most
208 * preferred to least.
210 static char gss_krb5_enctype_priority_list
[64];
212 static void gss_krb5_prepare_enctype_priority_list(void)
214 static const u32 gss_krb5_enctypes
[] = {
215 #if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2)
216 ENCTYPE_AES256_CTS_HMAC_SHA384_192
,
217 ENCTYPE_AES128_CTS_HMAC_SHA256_128
,
219 #if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA)
220 ENCTYPE_CAMELLIA256_CTS_CMAC
,
221 ENCTYPE_CAMELLIA128_CTS_CMAC
,
223 #if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1)
224 ENCTYPE_AES256_CTS_HMAC_SHA1_96
,
225 ENCTYPE_AES128_CTS_HMAC_SHA1_96
,
234 gss_krb5_enctype_priority_list
[0] = '\0';
235 for (total
= 0, i
= 0; i
< ARRAY_SIZE(gss_krb5_enctypes
); i
++) {
236 n
= sprintf(buf
, "%s%u", sep
, gss_krb5_enctypes
[i
]);
239 if (total
+ n
>= sizeof(gss_krb5_enctype_priority_list
))
241 strcat(gss_krb5_enctype_priority_list
, buf
);
248 * gss_krb5_lookup_enctype - Retrieve profile information for a given enctype
249 * @etype: ENCTYPE value
251 * Returns a pointer to a gss_krb5_enctype structure, or NULL if no
252 * matching etype is found.
255 const struct gss_krb5_enctype
*gss_krb5_lookup_enctype(u32 etype
)
259 for (i
= 0; i
< ARRAY_SIZE(supported_gss_krb5_enctypes
); i
++)
260 if (supported_gss_krb5_enctypes
[i
].etype
== etype
)
261 return &supported_gss_krb5_enctypes
[i
];
264 EXPORT_SYMBOL_IF_KUNIT(gss_krb5_lookup_enctype
);
266 static struct crypto_sync_skcipher
*
267 gss_krb5_alloc_cipher_v2(const char *cname
, const struct xdr_netobj
*key
)
269 struct crypto_sync_skcipher
*tfm
;
271 tfm
= crypto_alloc_sync_skcipher(cname
, 0, 0);
274 if (crypto_sync_skcipher_setkey(tfm
, key
->data
, key
->len
)) {
275 crypto_free_sync_skcipher(tfm
);
281 static struct crypto_ahash
*
282 gss_krb5_alloc_hash_v2(struct krb5_ctx
*kctx
, const struct xdr_netobj
*key
)
284 struct crypto_ahash
*tfm
;
286 tfm
= crypto_alloc_ahash(kctx
->gk5e
->cksum_name
, 0, CRYPTO_ALG_ASYNC
);
289 if (crypto_ahash_setkey(tfm
, key
->data
, key
->len
)) {
290 crypto_free_ahash(tfm
);
297 gss_krb5_import_ctx_v2(struct krb5_ctx
*ctx
, gfp_t gfp_mask
)
299 struct xdr_netobj keyin
= {
300 .len
= ctx
->gk5e
->keylength
,
303 struct xdr_netobj keyout
;
306 keyout
.data
= kmalloc(GSS_KRB5_MAX_KEYLEN
, gfp_mask
);
310 /* initiator seal encryption */
311 keyout
.len
= ctx
->gk5e
->Ke_length
;
312 if (krb5_derive_key(ctx
, &keyin
, &keyout
, KG_USAGE_INITIATOR_SEAL
,
313 KEY_USAGE_SEED_ENCRYPTION
, gfp_mask
))
315 ctx
->initiator_enc
= gss_krb5_alloc_cipher_v2(ctx
->gk5e
->encrypt_name
,
317 if (ctx
->initiator_enc
== NULL
)
319 if (ctx
->gk5e
->aux_cipher
) {
320 ctx
->initiator_enc_aux
=
321 gss_krb5_alloc_cipher_v2(ctx
->gk5e
->aux_cipher
,
323 if (ctx
->initiator_enc_aux
== NULL
)
327 /* acceptor seal encryption */
328 if (krb5_derive_key(ctx
, &keyin
, &keyout
, KG_USAGE_ACCEPTOR_SEAL
,
329 KEY_USAGE_SEED_ENCRYPTION
, gfp_mask
))
331 ctx
->acceptor_enc
= gss_krb5_alloc_cipher_v2(ctx
->gk5e
->encrypt_name
,
333 if (ctx
->acceptor_enc
== NULL
)
335 if (ctx
->gk5e
->aux_cipher
) {
336 ctx
->acceptor_enc_aux
=
337 gss_krb5_alloc_cipher_v2(ctx
->gk5e
->aux_cipher
,
339 if (ctx
->acceptor_enc_aux
== NULL
)
343 /* initiator sign checksum */
344 keyout
.len
= ctx
->gk5e
->Kc_length
;
345 if (krb5_derive_key(ctx
, &keyin
, &keyout
, KG_USAGE_INITIATOR_SIGN
,
346 KEY_USAGE_SEED_CHECKSUM
, gfp_mask
))
348 ctx
->initiator_sign
= gss_krb5_alloc_hash_v2(ctx
, &keyout
);
349 if (ctx
->initiator_sign
== NULL
)
352 /* acceptor sign checksum */
353 if (krb5_derive_key(ctx
, &keyin
, &keyout
, KG_USAGE_ACCEPTOR_SIGN
,
354 KEY_USAGE_SEED_CHECKSUM
, gfp_mask
))
356 ctx
->acceptor_sign
= gss_krb5_alloc_hash_v2(ctx
, &keyout
);
357 if (ctx
->acceptor_sign
== NULL
)
360 /* initiator seal integrity */
361 keyout
.len
= ctx
->gk5e
->Ki_length
;
362 if (krb5_derive_key(ctx
, &keyin
, &keyout
, KG_USAGE_INITIATOR_SEAL
,
363 KEY_USAGE_SEED_INTEGRITY
, gfp_mask
))
365 ctx
->initiator_integ
= gss_krb5_alloc_hash_v2(ctx
, &keyout
);
366 if (ctx
->initiator_integ
== NULL
)
369 /* acceptor seal integrity */
370 if (krb5_derive_key(ctx
, &keyin
, &keyout
, KG_USAGE_ACCEPTOR_SEAL
,
371 KEY_USAGE_SEED_INTEGRITY
, gfp_mask
))
373 ctx
->acceptor_integ
= gss_krb5_alloc_hash_v2(ctx
, &keyout
);
374 if (ctx
->acceptor_integ
== NULL
)
379 kfree_sensitive(keyout
.data
);
383 crypto_free_ahash(ctx
->acceptor_integ
);
384 crypto_free_ahash(ctx
->initiator_integ
);
385 crypto_free_ahash(ctx
->acceptor_sign
);
386 crypto_free_ahash(ctx
->initiator_sign
);
387 crypto_free_sync_skcipher(ctx
->acceptor_enc_aux
);
388 crypto_free_sync_skcipher(ctx
->acceptor_enc
);
389 crypto_free_sync_skcipher(ctx
->initiator_enc_aux
);
390 crypto_free_sync_skcipher(ctx
->initiator_enc
);
395 gss_import_v2_context(const void *p
, const void *end
, struct krb5_ctx
*ctx
,
403 p
= simple_get_bytes(p
, end
, &ctx
->flags
, sizeof(ctx
->flags
));
406 ctx
->initiate
= ctx
->flags
& KRB5_CTX_FLAG_INITIATOR
;
408 p
= simple_get_bytes(p
, end
, &time32
, sizeof(time32
));
411 /* unsigned 32-bit time overflows in year 2106 */
412 ctx
->endtime
= (time64_t
)time32
;
413 p
= simple_get_bytes(p
, end
, &seq_send64
, sizeof(seq_send64
));
416 atomic64_set(&ctx
->seq_send64
, seq_send64
);
417 /* set seq_send for use by "older" enctypes */
418 atomic_set(&ctx
->seq_send
, seq_send64
);
419 if (seq_send64
!= atomic_read(&ctx
->seq_send
)) {
420 dprintk("%s: seq_send64 %llx, seq_send %x overflow?\n", __func__
,
421 seq_send64
, atomic_read(&ctx
->seq_send
));
422 p
= ERR_PTR(-EINVAL
);
425 p
= simple_get_bytes(p
, end
, &ctx
->enctype
, sizeof(ctx
->enctype
));
428 ctx
->gk5e
= gss_krb5_lookup_enctype(ctx
->enctype
);
429 if (ctx
->gk5e
== NULL
) {
430 dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
432 p
= ERR_PTR(-EINVAL
);
435 keylen
= ctx
->gk5e
->keylength
;
437 p
= simple_get_bytes(p
, end
, ctx
->Ksess
, keylen
);
442 p
= ERR_PTR(-EINVAL
);
446 ctx
->mech_used
.data
= kmemdup(gss_kerberos_mech
.gm_oid
.data
,
447 gss_kerberos_mech
.gm_oid
.len
, gfp_mask
);
448 if (unlikely(ctx
->mech_used
.data
== NULL
)) {
449 p
= ERR_PTR(-ENOMEM
);
452 ctx
->mech_used
.len
= gss_kerberos_mech
.gm_oid
.len
;
454 ret
= gss_krb5_import_ctx_v2(ctx
, gfp_mask
);
463 kfree(ctx
->mech_used
.data
);
469 gss_krb5_import_sec_context(const void *p
, size_t len
, struct gss_ctx
*ctx_id
,
470 time64_t
*endtime
, gfp_t gfp_mask
)
472 const void *end
= (const void *)((const char *)p
+ len
);
473 struct krb5_ctx
*ctx
;
476 ctx
= kzalloc(sizeof(*ctx
), gfp_mask
);
480 ret
= gss_import_v2_context(p
, end
, ctx
, gfp_mask
);
481 memzero_explicit(&ctx
->Ksess
, sizeof(ctx
->Ksess
));
487 ctx_id
->internal_ctx_id
= ctx
;
489 *endtime
= ctx
->endtime
;
494 gss_krb5_delete_sec_context(void *internal_ctx
)
496 struct krb5_ctx
*kctx
= internal_ctx
;
498 crypto_free_sync_skcipher(kctx
->seq
);
499 crypto_free_sync_skcipher(kctx
->enc
);
500 crypto_free_sync_skcipher(kctx
->acceptor_enc
);
501 crypto_free_sync_skcipher(kctx
->initiator_enc
);
502 crypto_free_sync_skcipher(kctx
->acceptor_enc_aux
);
503 crypto_free_sync_skcipher(kctx
->initiator_enc_aux
);
504 crypto_free_ahash(kctx
->acceptor_sign
);
505 crypto_free_ahash(kctx
->initiator_sign
);
506 crypto_free_ahash(kctx
->acceptor_integ
);
507 crypto_free_ahash(kctx
->initiator_integ
);
508 kfree(kctx
->mech_used
.data
);
513 * gss_krb5_get_mic - get_mic for the Kerberos GSS mechanism
515 * @text: plaintext to checksum
516 * @token: buffer into which to write the computed checksum
519 * %GSS_S_COMPLETE - success, and @token is filled in
520 * %GSS_S_FAILURE - checksum could not be generated
521 * %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
523 static u32
gss_krb5_get_mic(struct gss_ctx
*gctx
, struct xdr_buf
*text
,
524 struct xdr_netobj
*token
)
526 struct krb5_ctx
*kctx
= gctx
->internal_ctx_id
;
528 return kctx
->gk5e
->get_mic(kctx
, text
, token
);
532 * gss_krb5_verify_mic - verify_mic for the Kerberos GSS mechanism
534 * @message_buffer: plaintext to check
535 * @read_token: received checksum to check
538 * %GSS_S_COMPLETE - computed and received checksums match
539 * %GSS_S_DEFECTIVE_TOKEN - received checksum is not valid
540 * %GSS_S_BAD_SIG - computed and received checksums do not match
541 * %GSS_S_FAILURE - received checksum could not be checked
542 * %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
544 static u32
gss_krb5_verify_mic(struct gss_ctx
*gctx
,
545 struct xdr_buf
*message_buffer
,
546 struct xdr_netobj
*read_token
)
548 struct krb5_ctx
*kctx
= gctx
->internal_ctx_id
;
550 return kctx
->gk5e
->verify_mic(kctx
, message_buffer
, read_token
);
554 * gss_krb5_wrap - gss_wrap for the Kerberos GSS mechanism
555 * @gctx: initialized GSS context
556 * @offset: byte offset in @buf to start writing the cipher text
557 * @buf: OUT: send buffer
558 * @pages: plaintext to wrap
561 * %GSS_S_COMPLETE - success, @buf has been updated
562 * %GSS_S_FAILURE - @buf could not be wrapped
563 * %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
565 static u32
gss_krb5_wrap(struct gss_ctx
*gctx
, int offset
,
566 struct xdr_buf
*buf
, struct page
**pages
)
568 struct krb5_ctx
*kctx
= gctx
->internal_ctx_id
;
570 return kctx
->gk5e
->wrap(kctx
, offset
, buf
, pages
);
574 * gss_krb5_unwrap - gss_unwrap for the Kerberos GSS mechanism
575 * @gctx: initialized GSS context
576 * @offset: starting byte offset into @buf
577 * @len: size of ciphertext to unwrap
578 * @buf: ciphertext to unwrap
581 * %GSS_S_COMPLETE - success, @buf has been updated
582 * %GSS_S_DEFECTIVE_TOKEN - received blob is not valid
583 * %GSS_S_BAD_SIG - computed and received checksums do not match
584 * %GSS_S_FAILURE - @buf could not be unwrapped
585 * %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
587 static u32
gss_krb5_unwrap(struct gss_ctx
*gctx
, int offset
,
588 int len
, struct xdr_buf
*buf
)
590 struct krb5_ctx
*kctx
= gctx
->internal_ctx_id
;
592 return kctx
->gk5e
->unwrap(kctx
, offset
, len
, buf
,
593 &gctx
->slack
, &gctx
->align
);
596 static const struct gss_api_ops gss_kerberos_ops
= {
597 .gss_import_sec_context
= gss_krb5_import_sec_context
,
598 .gss_get_mic
= gss_krb5_get_mic
,
599 .gss_verify_mic
= gss_krb5_verify_mic
,
600 .gss_wrap
= gss_krb5_wrap
,
601 .gss_unwrap
= gss_krb5_unwrap
,
602 .gss_delete_sec_context
= gss_krb5_delete_sec_context
,
605 static struct pf_desc gss_kerberos_pfs
[] = {
607 .pseudoflavor
= RPC_AUTH_GSS_KRB5
,
608 .qop
= GSS_C_QOP_DEFAULT
,
609 .service
= RPC_GSS_SVC_NONE
,
613 .pseudoflavor
= RPC_AUTH_GSS_KRB5I
,
614 .qop
= GSS_C_QOP_DEFAULT
,
615 .service
= RPC_GSS_SVC_INTEGRITY
,
620 .pseudoflavor
= RPC_AUTH_GSS_KRB5P
,
621 .qop
= GSS_C_QOP_DEFAULT
,
622 .service
= RPC_GSS_SVC_PRIVACY
,
628 MODULE_ALIAS("rpc-auth-gss-krb5");
629 MODULE_ALIAS("rpc-auth-gss-krb5i");
630 MODULE_ALIAS("rpc-auth-gss-krb5p");
631 MODULE_ALIAS("rpc-auth-gss-390003");
632 MODULE_ALIAS("rpc-auth-gss-390004");
633 MODULE_ALIAS("rpc-auth-gss-390005");
634 MODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2");
636 static struct gss_api_mech gss_kerberos_mech
= {
638 .gm_owner
= THIS_MODULE
,
639 .gm_oid
= { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" },
640 .gm_ops
= &gss_kerberos_ops
,
641 .gm_pf_num
= ARRAY_SIZE(gss_kerberos_pfs
),
642 .gm_pfs
= gss_kerberos_pfs
,
643 .gm_upcall_enctypes
= gss_krb5_enctype_priority_list
,
646 static int __init
init_kerberos_module(void)
650 gss_krb5_prepare_enctype_priority_list();
651 status
= gss_mech_register(&gss_kerberos_mech
);
653 printk("Failed to register kerberos gss mechanism!\n");
657 static void __exit
cleanup_kerberos_module(void)
659 gss_mech_unregister(&gss_kerberos_mech
);
662 MODULE_DESCRIPTION("Sun RPC Kerberos 5 module");
663 MODULE_LICENSE("GPL");
664 module_init(init_kerberos_module
);
665 module_exit(cleanup_kerberos_module
);