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