gss_krb5: add support for new token formats in rfc4121
[linux-2.6.git] / net / sunrpc / auth_gss / gss_krb5_unseal.c
index 3e15bdb..4ede4cc 100644 (file)
@@ -141,6 +141,64 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
        return GSS_S_COMPLETE;
 }
 
+static u32
+gss_verify_mic_v2(struct krb5_ctx *ctx,
+               struct xdr_buf *message_buffer, struct xdr_netobj *read_token)
+{
+       char cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
+       struct xdr_netobj cksumobj = {.len = sizeof(cksumdata),
+                                     .data = cksumdata};
+       s32 now;
+       u64 seqnum;
+       u8 *ptr = read_token->data;
+       u8 *cksumkey;
+       u8 flags;
+       int i;
+
+       dprintk("RPC:       %s\n", __func__);
+
+       if (be16_to_cpu(*((__be16 *)ptr)) != KG2_TOK_MIC)
+               return GSS_S_DEFECTIVE_TOKEN;
+
+       flags = ptr[2];
+       if ((!ctx->initiate && (flags & KG2_TOKEN_FLAG_SENTBYACCEPTOR)) ||
+           (ctx->initiate && !(flags & KG2_TOKEN_FLAG_SENTBYACCEPTOR)))
+               return GSS_S_BAD_SIG;
+
+       if (flags & KG2_TOKEN_FLAG_SEALED) {
+               dprintk("%s: token has unexpected sealed flag\n", __func__);
+               return GSS_S_FAILURE;
+       }
+
+       for (i = 3; i < 8; i++)
+               if (ptr[i] != 0xff)
+                       return GSS_S_DEFECTIVE_TOKEN;
+
+       if (ctx->initiate)
+               cksumkey = ctx->acceptor_sign;
+       else
+               cksumkey = ctx->initiator_sign;
+
+       if (make_checksum_v2(ctx, ptr, GSS_KRB5_TOK_HDR_LEN, message_buffer, 0,
+                            cksumkey, &cksumobj))
+               return GSS_S_FAILURE;
+
+       if (memcmp(cksumobj.data, ptr + GSS_KRB5_TOK_HDR_LEN,
+                               ctx->gk5e->cksumlength))
+               return GSS_S_BAD_SIG;
+
+       /* it got through unscathed.  Make sure the context is unexpired */
+       now = get_seconds();
+       if (now > ctx->endtime)
+               return GSS_S_CONTEXT_EXPIRED;
+
+       /* do sequencing checks */
+
+       seqnum = be64_to_cpup((__be64 *)ptr + 8);
+
+       return GSS_S_COMPLETE;
+}
+
 u32
 gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
                        struct xdr_buf *message_buffer,
@@ -154,6 +212,9 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
        case ENCTYPE_DES_CBC_RAW:
        case ENCTYPE_DES3_CBC_RAW:
                return gss_verify_mic_v1(ctx, message_buffer, read_token);
+       case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+       case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+               return gss_verify_mic_v2(ctx, message_buffer, read_token);
        }
 }