diff options
Diffstat (limited to 'net/sunrpc/auth_gss/gss_krb5_unseal.c')
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_unseal.c | 113 |
1 files changed, 101 insertions, 12 deletions
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c index ce6c247edad0..6cd930f3678f 100644 --- a/net/sunrpc/auth_gss/gss_krb5_unseal.c +++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5unseal.c | 4 | * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5unseal.c |
5 | * | 5 | * |
6 | * Copyright (c) 2000 The Regents of the University of Michigan. | 6 | * Copyright (c) 2000-2008 The Regents of the University of Michigan. |
7 | * All rights reserved. | 7 | * All rights reserved. |
8 | * | 8 | * |
9 | * Andy Adamson <andros@umich.edu> | 9 | * Andy Adamson <andros@umich.edu> |
@@ -70,20 +70,21 @@ | |||
70 | /* read_token is a mic token, and message_buffer is the data that the mic was | 70 | /* read_token is a mic token, and message_buffer is the data that the mic was |
71 | * supposedly taken over. */ | 71 | * supposedly taken over. */ |
72 | 72 | ||
73 | u32 | 73 | static u32 |
74 | gss_verify_mic_kerberos(struct gss_ctx *gss_ctx, | 74 | gss_verify_mic_v1(struct krb5_ctx *ctx, |
75 | struct xdr_buf *message_buffer, struct xdr_netobj *read_token) | 75 | struct xdr_buf *message_buffer, struct xdr_netobj *read_token) |
76 | { | 76 | { |
77 | struct krb5_ctx *ctx = gss_ctx->internal_ctx_id; | ||
78 | int signalg; | 77 | int signalg; |
79 | int sealalg; | 78 | int sealalg; |
80 | char cksumdata[16]; | 79 | char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; |
81 | struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; | 80 | struct xdr_netobj md5cksum = {.len = sizeof(cksumdata), |
81 | .data = cksumdata}; | ||
82 | s32 now; | 82 | s32 now; |
83 | int direction; | 83 | int direction; |
84 | u32 seqnum; | 84 | u32 seqnum; |
85 | unsigned char *ptr = (unsigned char *)read_token->data; | 85 | unsigned char *ptr = (unsigned char *)read_token->data; |
86 | int bodysize; | 86 | int bodysize; |
87 | u8 *cksumkey; | ||
87 | 88 | ||
88 | dprintk("RPC: krb5_read_token\n"); | 89 | dprintk("RPC: krb5_read_token\n"); |
89 | 90 | ||
@@ -98,7 +99,7 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx, | |||
98 | /* XXX sanity-check bodysize?? */ | 99 | /* XXX sanity-check bodysize?? */ |
99 | 100 | ||
100 | signalg = ptr[2] + (ptr[3] << 8); | 101 | signalg = ptr[2] + (ptr[3] << 8); |
101 | if (signalg != SGN_ALG_DES_MAC_MD5) | 102 | if (signalg != ctx->gk5e->signalg) |
102 | return GSS_S_DEFECTIVE_TOKEN; | 103 | return GSS_S_DEFECTIVE_TOKEN; |
103 | 104 | ||
104 | sealalg = ptr[4] + (ptr[5] << 8); | 105 | sealalg = ptr[4] + (ptr[5] << 8); |
@@ -108,13 +109,17 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx, | |||
108 | if ((ptr[6] != 0xff) || (ptr[7] != 0xff)) | 109 | if ((ptr[6] != 0xff) || (ptr[7] != 0xff)) |
109 | return GSS_S_DEFECTIVE_TOKEN; | 110 | return GSS_S_DEFECTIVE_TOKEN; |
110 | 111 | ||
111 | if (make_checksum("md5", ptr, 8, message_buffer, 0, &md5cksum)) | 112 | if (ctx->gk5e->keyed_cksum) |
112 | return GSS_S_FAILURE; | 113 | cksumkey = ctx->cksum; |
114 | else | ||
115 | cksumkey = NULL; | ||
113 | 116 | ||
114 | if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, 16)) | 117 | if (make_checksum(ctx, ptr, 8, message_buffer, 0, |
118 | cksumkey, KG_USAGE_SIGN, &md5cksum)) | ||
115 | return GSS_S_FAILURE; | 119 | return GSS_S_FAILURE; |
116 | 120 | ||
117 | if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN, 8)) | 121 | if (memcmp(md5cksum.data, ptr + GSS_KRB5_TOK_HDR_LEN, |
122 | ctx->gk5e->cksumlength)) | ||
118 | return GSS_S_BAD_SIG; | 123 | return GSS_S_BAD_SIG; |
119 | 124 | ||
120 | /* it got through unscathed. Make sure the context is unexpired */ | 125 | /* it got through unscathed. Make sure the context is unexpired */ |
@@ -126,7 +131,8 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx, | |||
126 | 131 | ||
127 | /* do sequencing checks */ | 132 | /* do sequencing checks */ |
128 | 133 | ||
129 | if (krb5_get_seq_num(ctx->seq, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8, &direction, &seqnum)) | 134 | if (krb5_get_seq_num(ctx, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8, |
135 | &direction, &seqnum)) | ||
130 | return GSS_S_FAILURE; | 136 | return GSS_S_FAILURE; |
131 | 137 | ||
132 | if ((ctx->initiate && direction != 0xff) || | 138 | if ((ctx->initiate && direction != 0xff) || |
@@ -135,3 +141,86 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx, | |||
135 | 141 | ||
136 | return GSS_S_COMPLETE; | 142 | return GSS_S_COMPLETE; |
137 | } | 143 | } |
144 | |||
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; | ||
158 | unsigned int cksum_usage; | ||
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 | |||
179 | if (ctx->initiate) { | ||
180 | cksumkey = ctx->acceptor_sign; | ||
181 | cksum_usage = KG_USAGE_ACCEPTOR_SIGN; | ||
182 | } else { | ||
183 | cksumkey = ctx->initiator_sign; | ||
184 | cksum_usage = KG_USAGE_INITIATOR_SIGN; | ||
185 | } | ||
186 | |||
187 | if (make_checksum_v2(ctx, ptr, GSS_KRB5_TOK_HDR_LEN, message_buffer, 0, | ||
188 | cksumkey, cksum_usage, &cksumobj)) | ||
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 | |||
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: | ||
218 | case ENCTYPE_DES3_CBC_RAW: | ||
219 | case ENCTYPE_ARCFOUR_HMAC: | ||
220 | return gss_verify_mic_v1(ctx, message_buffer, read_token); | ||
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); | ||
224 | } | ||
225 | } | ||
226 | |||