Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/net/sunrpc/gss_krb5_unseal.c | |
3 | * | |
4 | * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5unseal.c | |
5 | * | |
81d4a433 | 6 | * Copyright (c) 2000-2008 The Regents of the University of Michigan. |
1da177e4 LT |
7 | * All rights reserved. |
8 | * | |
9 | * Andy Adamson <andros@umich.edu> | |
10 | */ | |
11 | ||
12 | /* | |
13 | * Copyright 1993 by OpenVision Technologies, Inc. | |
14 | * | |
15 | * Permission to use, copy, modify, distribute, and sell this software | |
16 | * and its documentation for any purpose is hereby granted without fee, | |
17 | * provided that the above copyright notice appears in all copies and | |
18 | * that both that copyright notice and this permission notice appear in | |
19 | * supporting documentation, and that the name of OpenVision not be used | |
20 | * in advertising or publicity pertaining to distribution of the software | |
21 | * without specific, written prior permission. OpenVision makes no | |
22 | * representations about the suitability of this software for any | |
23 | * purpose. It is provided "as is" without express or implied warranty. | |
24 | * | |
25 | * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |
26 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |
27 | * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |
28 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |
29 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | |
30 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |
31 | * PERFORMANCE OF THIS SOFTWARE. | |
32 | */ | |
33 | ||
34 | /* | |
35 | * Copyright (C) 1998 by the FundsXpress, INC. | |
36 | * | |
37 | * All rights reserved. | |
38 | * | |
39 | * Export of this software from the United States of America may require | |
40 | * a specific license from the United States Government. It is the | |
41 | * responsibility of any person or organization contemplating export to | |
42 | * obtain such a license before exporting. | |
43 | * | |
44 | * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and | |
45 | * distribute this software and its documentation for any purpose and | |
46 | * without fee is hereby granted, provided that the above copyright | |
47 | * notice appear in all copies and that both that copyright notice and | |
48 | * this permission notice appear in supporting documentation, and that | |
49 | * the name of FundsXpress. not be used in advertising or publicity pertaining | |
50 | * to distribution of the software without specific, written prior | |
51 | * permission. FundsXpress makes no representations about the suitability of | |
52 | * this software for any purpose. It is provided "as is" without express | |
53 | * or implied warranty. | |
54 | * | |
55 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
56 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
57 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
58 | */ | |
59 | ||
60 | #include <linux/types.h> | |
1da177e4 LT |
61 | #include <linux/jiffies.h> |
62 | #include <linux/sunrpc/gss_krb5.h> | |
63 | #include <linux/crypto.h> | |
64 | ||
65 | #ifdef RPC_DEBUG | |
66 | # define RPCDBG_FACILITY RPCDBG_AUTH | |
67 | #endif | |
68 | ||
69 | ||
bfa91516 BF |
70 | /* read_token is a mic token, and message_buffer is the data that the mic was |
71 | * supposedly taken over. */ | |
1da177e4 | 72 | |
1ac3719a KC |
73 | static u32 |
74 | gss_verify_mic_v1(struct krb5_ctx *ctx, | |
a0857d03 | 75 | struct xdr_buf *message_buffer, struct xdr_netobj *read_token) |
1da177e4 LT |
76 | { |
77 | int signalg; | |
78 | int sealalg; | |
81d4a433 KC |
79 | char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; |
80 | struct xdr_netobj md5cksum = {.len = sizeof(cksumdata), | |
81 | .data = cksumdata}; | |
1da177e4 LT |
82 | s32 now; |
83 | int direction; | |
5743d65c | 84 | u32 seqnum; |
1da177e4 LT |
85 | unsigned char *ptr = (unsigned char *)read_token->data; |
86 | int bodysize; | |
e1f6c07b | 87 | u8 *cksumkey; |
1da177e4 | 88 | |
8885cb36 | 89 | dprintk("RPC: krb5_read_token\n"); |
1da177e4 LT |
90 | |
91 | if (g_verify_token_header(&ctx->mech_used, &bodysize, &ptr, | |
92 | read_token->len)) | |
39a21dd1 | 93 | return GSS_S_DEFECTIVE_TOKEN; |
1da177e4 | 94 | |
d00953a5 KC |
95 | if ((ptr[0] != ((KG_TOK_MIC_MSG >> 8) & 0xff)) || |
96 | (ptr[1] != (KG_TOK_MIC_MSG & 0xff))) | |
39a21dd1 | 97 | return GSS_S_DEFECTIVE_TOKEN; |
1da177e4 LT |
98 | |
99 | /* XXX sanity-check bodysize?? */ | |
100 | ||
d00953a5 | 101 | signalg = ptr[2] + (ptr[3] << 8); |
81d4a433 | 102 | if (signalg != ctx->gk5e->signalg) |
39a21dd1 | 103 | return GSS_S_DEFECTIVE_TOKEN; |
1da177e4 | 104 | |
d00953a5 | 105 | sealalg = ptr[4] + (ptr[5] << 8); |
94efa934 | 106 | if (sealalg != SEAL_ALG_NONE) |
39a21dd1 | 107 | return GSS_S_DEFECTIVE_TOKEN; |
94efa934 | 108 | |
d00953a5 | 109 | if ((ptr[6] != 0xff) || (ptr[7] != 0xff)) |
39a21dd1 | 110 | return GSS_S_DEFECTIVE_TOKEN; |
1da177e4 | 111 | |
e1f6c07b KC |
112 | if (ctx->gk5e->keyed_cksum) |
113 | cksumkey = ctx->cksum; | |
114 | else | |
115 | cksumkey = NULL; | |
5eb064f9 | 116 | |
e1f6c07b | 117 | if (make_checksum(ctx, ptr, 8, message_buffer, 0, |
8b237076 | 118 | cksumkey, KG_USAGE_SIGN, &md5cksum)) |
39a21dd1 | 119 | return GSS_S_FAILURE; |
1da177e4 | 120 | |
e1f6c07b | 121 | if (memcmp(md5cksum.data, ptr + GSS_KRB5_TOK_HDR_LEN, |
81d4a433 | 122 | ctx->gk5e->cksumlength)) |
39a21dd1 | 123 | return GSS_S_BAD_SIG; |
1da177e4 LT |
124 | |
125 | /* it got through unscathed. Make sure the context is unexpired */ | |
126 | ||
1da177e4 LT |
127 | now = get_seconds(); |
128 | ||
1da177e4 | 129 | if (now > ctx->endtime) |
39a21dd1 | 130 | return GSS_S_CONTEXT_EXPIRED; |
1da177e4 LT |
131 | |
132 | /* do sequencing checks */ | |
133 | ||
1dbd9029 KC |
134 | if (krb5_get_seq_num(ctx, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8, |
135 | &direction, &seqnum)) | |
39a21dd1 | 136 | return GSS_S_FAILURE; |
1da177e4 LT |
137 | |
138 | if ((ctx->initiate && direction != 0xff) || | |
139 | (!ctx->initiate && direction != 0)) | |
39a21dd1 | 140 | return GSS_S_BAD_SIG; |
1da177e4 | 141 | |
39a21dd1 | 142 | return GSS_S_COMPLETE; |
1da177e4 | 143 | } |
1ac3719a | 144 | |
de9c17eb KC |
145 | static u32 |
146 | gss_verify_mic_v2(struct krb5_ctx *ctx, | |
147 | struct xdr_buf *message_buffer, struct xdr_netobj *read_token) | |
148 | { | |
149 | char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; | |
150 | struct xdr_netobj cksumobj = {.len = sizeof(cksumdata), | |
151 | .data = cksumdata}; | |
152 | s32 now; | |
153 | u64 seqnum; | |
154 | u8 *ptr = read_token->data; | |
155 | u8 *cksumkey; | |
156 | u8 flags; | |
157 | int i; | |
8b237076 | 158 | unsigned int cksum_usage; |
de9c17eb KC |
159 | |
160 | dprintk("RPC: %s\n", __func__); | |
161 | ||
162 | if (be16_to_cpu(*((__be16 *)ptr)) != KG2_TOK_MIC) | |
163 | return GSS_S_DEFECTIVE_TOKEN; | |
164 | ||
165 | flags = ptr[2]; | |
166 | if ((!ctx->initiate && (flags & KG2_TOKEN_FLAG_SENTBYACCEPTOR)) || | |
167 | (ctx->initiate && !(flags & KG2_TOKEN_FLAG_SENTBYACCEPTOR))) | |
168 | return GSS_S_BAD_SIG; | |
169 | ||
170 | if (flags & KG2_TOKEN_FLAG_SEALED) { | |
171 | dprintk("%s: token has unexpected sealed flag\n", __func__); | |
172 | return GSS_S_FAILURE; | |
173 | } | |
174 | ||
175 | for (i = 3; i < 8; i++) | |
176 | if (ptr[i] != 0xff) | |
177 | return GSS_S_DEFECTIVE_TOKEN; | |
178 | ||
8b237076 | 179 | if (ctx->initiate) { |
de9c17eb | 180 | cksumkey = ctx->acceptor_sign; |
8b237076 KC |
181 | cksum_usage = KG_USAGE_ACCEPTOR_SIGN; |
182 | } else { | |
de9c17eb | 183 | cksumkey = ctx->initiator_sign; |
8b237076 KC |
184 | cksum_usage = KG_USAGE_INITIATOR_SIGN; |
185 | } | |
de9c17eb KC |
186 | |
187 | if (make_checksum_v2(ctx, ptr, GSS_KRB5_TOK_HDR_LEN, message_buffer, 0, | |
8b237076 | 188 | cksumkey, cksum_usage, &cksumobj)) |
de9c17eb KC |
189 | return GSS_S_FAILURE; |
190 | ||
191 | if (memcmp(cksumobj.data, ptr + GSS_KRB5_TOK_HDR_LEN, | |
192 | ctx->gk5e->cksumlength)) | |
193 | return GSS_S_BAD_SIG; | |
194 | ||
195 | /* it got through unscathed. Make sure the context is unexpired */ | |
196 | now = get_seconds(); | |
197 | if (now > ctx->endtime) | |
198 | return GSS_S_CONTEXT_EXPIRED; | |
199 | ||
200 | /* do sequencing checks */ | |
201 | ||
202 | seqnum = be64_to_cpup((__be64 *)ptr + 8); | |
203 | ||
204 | return GSS_S_COMPLETE; | |
205 | } | |
206 | ||
1ac3719a KC |
207 | u32 |
208 | gss_verify_mic_kerberos(struct gss_ctx *gss_ctx, | |
209 | struct xdr_buf *message_buffer, | |
210 | struct xdr_netobj *read_token) | |
211 | { | |
212 | struct krb5_ctx *ctx = gss_ctx->internal_ctx_id; | |
213 | ||
214 | switch (ctx->enctype) { | |
215 | default: | |
216 | BUG(); | |
217 | case ENCTYPE_DES_CBC_RAW: | |
958142e9 | 218 | case ENCTYPE_DES3_CBC_RAW: |
fffdaef2 | 219 | case ENCTYPE_ARCFOUR_HMAC: |
1ac3719a | 220 | return gss_verify_mic_v1(ctx, message_buffer, read_token); |
de9c17eb KC |
221 | case ENCTYPE_AES128_CTS_HMAC_SHA1_96: |
222 | case ENCTYPE_AES256_CTS_HMAC_SHA1_96: | |
223 | return gss_verify_mic_v2(ctx, message_buffer, read_token); | |
1ac3719a KC |
224 | } |
225 | } | |
226 |