1 /*
2 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
3 *
4 */
5
6 #include <gssrpc/rpc.h>
7 #include <stdio.h>
8
9 #include <gssapi/gssapi.h>
10 #include <gssrpc/auth_gssapi.h>
11
12 #include "gssrpcint.h"
13
14 #ifdef __CODECENTER__
15 #define DEBUG_GSSAPI 1
16 #endif
17
18 #ifdef DEBUG_GSSAPI
19 int misc_debug_gssapi = DEBUG_GSSAPI;
20 extern void gssrpcint_printf(const char *, ...);
21 #define L_PRINTF(l,args) if (misc_debug_gssapi >= l) gssrpcint_printf args
22 #define PRINTF(args) L_PRINTF(99, args)
23 #define AUTH_GSSAPI_DISPLAY_STATUS(args) \
24 if (misc_debug_gssapi) auth_gssapi_display_status args
25 #else
26 #define PRINTF(args)
27 #define L_PRINTF(l, args)
28 #define AUTH_GSSAPI_DISPLAY_STATUS(args)
29 #endif
30
31 static void auth_gssapi_display_status_1
32 (char *, OM_uint32, int, int);
33
xdr_gss_buf(XDR * xdrs,gss_buffer_t buf)34 bool_t xdr_gss_buf(
35 XDR *xdrs,
36 gss_buffer_t buf)
37 {
38 /*
39 * On decode, xdr_bytes will only allocate buf->value if the
40 * length read in is < maxsize (last arg). This is dumb, because
41 * the whole point of allocating memory is so that I don't *have*
42 * to know the maximum length. -1 effectively disables this
43 * braindamage.
44 */
45 bool_t result;
46 /* Fix type mismatches between APIs. */
47 unsigned int length = buf->length;
48 char *cp = buf->value;
49 result = xdr_bytes(xdrs, &cp, &length,
50 (xdrs->x_op == XDR_DECODE && buf->value == NULL)
51 ? (unsigned int) -1 : (unsigned int) buf->length);
52 buf->value = cp;
53 buf->length = length;
54 return result;
55 }
56
xdr_authgssapi_creds(XDR * xdrs,auth_gssapi_creds * creds)57 bool_t xdr_authgssapi_creds(
58 XDR *xdrs,
59 auth_gssapi_creds *creds)
60 {
61 if (! xdr_u_int32(xdrs, &creds->version) ||
62 ! xdr_bool(xdrs, &creds->auth_msg) ||
63 ! xdr_gss_buf(xdrs, &creds->client_handle))
64 return FALSE;
65 return TRUE;
66 }
67
xdr_authgssapi_init_arg(XDR * xdrs,auth_gssapi_init_arg * init_arg)68 bool_t xdr_authgssapi_init_arg(
69 XDR *xdrs,
70 auth_gssapi_init_arg *init_arg)
71 {
72 if (! xdr_u_int32(xdrs, &init_arg->version) ||
73 ! xdr_gss_buf(xdrs, &init_arg->token))
74 return FALSE;
75 return TRUE;
76 }
77
xdr_authgssapi_init_res(XDR * xdrs,auth_gssapi_init_res * init_res)78 bool_t xdr_authgssapi_init_res(
79 XDR *xdrs,
80 auth_gssapi_init_res *init_res)
81 {
82 if (! xdr_u_int32(xdrs, &init_res->version) ||
83 ! xdr_gss_buf(xdrs, &init_res->client_handle) ||
84 ! xdr_u_int32(xdrs, &init_res->gss_major) ||
85 ! xdr_u_int32(xdrs, &init_res->gss_minor) ||
86 ! xdr_gss_buf(xdrs, &init_res->token) ||
87 ! xdr_gss_buf(xdrs, &init_res->signed_isn))
88 return FALSE;
89 return TRUE;
90 }
91
auth_gssapi_seal_seq(gss_ctx_id_t context,uint32_t seq_num,gss_buffer_t out_buf)92 bool_t auth_gssapi_seal_seq(
93 gss_ctx_id_t context,
94 uint32_t seq_num,
95 gss_buffer_t out_buf)
96 {
97 gss_buffer_desc in_buf;
98 OM_uint32 gssstat, minor_stat;
99 uint32_t nl_seq_num;
100
101 nl_seq_num = htonl(seq_num);
102
103 in_buf.length = sizeof(uint32_t);
104 in_buf.value = (char *) &nl_seq_num;
105 gssstat = gss_seal(&minor_stat, context, 0, GSS_C_QOP_DEFAULT,
106 &in_buf, NULL, out_buf);
107 if (gssstat != GSS_S_COMPLETE) {
108 PRINTF(("gssapi_seal_seq: failed\n"));
109 AUTH_GSSAPI_DISPLAY_STATUS(("sealing sequence number",
110 gssstat, minor_stat));
111 return FALSE;
112 }
113 return TRUE;
114 }
115
auth_gssapi_unseal_seq(gss_ctx_id_t context,gss_buffer_t in_buf,uint32_t * seq_num)116 bool_t auth_gssapi_unseal_seq(
117 gss_ctx_id_t context,
118 gss_buffer_t in_buf,
119 uint32_t *seq_num)
120 {
121 gss_buffer_desc out_buf;
122 OM_uint32 gssstat, minor_stat;
123 uint32_t nl_seq_num;
124
125 gssstat = gss_unseal(&minor_stat, context, in_buf, &out_buf,
126 NULL, NULL);
127 if (gssstat != GSS_S_COMPLETE) {
128 PRINTF(("gssapi_unseal_seq: failed\n"));
129 AUTH_GSSAPI_DISPLAY_STATUS(("unsealing sequence number",
130 gssstat, minor_stat));
131 return FALSE;
132 } else if (out_buf.length != sizeof(uint32_t)) {
133 PRINTF(("gssapi_unseal_seq: unseal gave %d bytes\n",
134 (int) out_buf.length));
135 gss_release_buffer(&minor_stat, &out_buf);
136 return FALSE;
137 }
138
139 nl_seq_num = *((uint32_t *) out_buf.value);
140 *seq_num = (uint32_t) ntohl(nl_seq_num);
141 gss_release_buffer(&minor_stat, &out_buf);
142
143 return TRUE;
144 }
145
auth_gssapi_display_status(char * msg,OM_uint32 major,OM_uint32 minor)146 void auth_gssapi_display_status(
147 char *msg,
148 OM_uint32 major,
149 OM_uint32 minor)
150 {
151 auth_gssapi_display_status_1(msg, major, GSS_C_GSS_CODE, 0);
152 auth_gssapi_display_status_1(msg, minor, GSS_C_MECH_CODE, 0);
153 }
154
auth_gssapi_display_status_1(char * m,OM_uint32 code,int type,int rec)155 static void auth_gssapi_display_status_1(
156 char *m,
157 OM_uint32 code,
158 int type,
159 int rec)
160 {
161 OM_uint32 gssstat, minor_stat;
162 gss_buffer_desc msg;
163 OM_uint32 msg_ctx;
164
165 msg_ctx = 0;
166 while (1) {
167 gssstat = gss_display_status(&minor_stat, code,
168 type, GSS_C_NULL_OID,
169 &msg_ctx, &msg);
170 if (gssstat != GSS_S_COMPLETE) {
171 if (!rec) {
172 auth_gssapi_display_status_1(m,gssstat,GSS_C_GSS_CODE,1);
173 auth_gssapi_display_status_1(m, minor_stat,
174 GSS_C_MECH_CODE, 1);
175 } else {
176 fputs ("GSS-API authentication error ", stderr);
177 fwrite (msg.value, msg.length, 1, stderr);
178 fputs (": recursive failure!\n", stderr);
179 }
180 return;
181 }
182
183 fprintf (stderr, "GSS-API authentication error %s: ", m);
184 fwrite (msg.value, msg.length, 1, stderr);
185 putc ('\n', stderr);
186 if (misc_debug_gssapi)
187 gssrpcint_printf("GSS-API authentication error %s: %*s\n",
188 m, (int)msg.length, (char *) msg.value);
189 (void) gss_release_buffer(&minor_stat, &msg);
190
191 if (!msg_ctx)
192 break;
193 }
194 }
195
auth_gssapi_wrap_data(OM_uint32 * major,OM_uint32 * minor,gss_ctx_id_t context,uint32_t seq_num,XDR * out_xdrs,bool_t (* xdr_func)(),caddr_t xdr_ptr)196 bool_t auth_gssapi_wrap_data(
197 OM_uint32 *major,
198 OM_uint32 *minor,
199 gss_ctx_id_t context,
200 uint32_t seq_num,
201 XDR *out_xdrs,
202 bool_t (*xdr_func)(),
203 caddr_t xdr_ptr)
204 {
205 gss_buffer_desc in_buf, out_buf;
206 XDR temp_xdrs;
207 int conf_state;
208 unsigned int length;
209 char *cp;
210
211 PRINTF(("gssapi_wrap_data: starting\n"));
212
213 *major = GSS_S_COMPLETE;
214 *minor = 0; /* assumption */
215
216 xdralloc_create(&temp_xdrs, XDR_ENCODE);
217
218 /* serialize the sequence number into local memory */
219 PRINTF(("gssapi_wrap_data: encoding seq_num %d\n", seq_num));
220 if (! xdr_u_int32(&temp_xdrs, &seq_num)) {
221 PRINTF(("gssapi_wrap_data: serializing seq_num failed\n"));
222 XDR_DESTROY(&temp_xdrs);
223 return FALSE;
224 }
225
226 /* serialize the arguments into local memory */
227 if (!(*xdr_func)(&temp_xdrs, xdr_ptr)) {
228 PRINTF(("gssapi_wrap_data: serializing arguments failed\n"));
229 XDR_DESTROY(&temp_xdrs);
230 return FALSE;
231 }
232
233 in_buf.length = xdr_getpos(&temp_xdrs);
234 in_buf.value = xdralloc_getdata(&temp_xdrs);
235
236 *major = gss_seal(minor, context, 1,
237 GSS_C_QOP_DEFAULT, &in_buf, &conf_state,
238 &out_buf);
239 if (*major != GSS_S_COMPLETE) {
240 XDR_DESTROY(&temp_xdrs);
241 return FALSE;
242 }
243
244 PRINTF(("gssapi_wrap_data: %d bytes data, %d bytes sealed\n",
245 (int) in_buf.length, (int) out_buf.length));
246
247 /* write the token */
248 length = out_buf.length;
249 cp = out_buf.value;
250 if (! xdr_bytes(out_xdrs, &cp, &length, out_buf.length)) {
251 PRINTF(("gssapi_wrap_data: serializing encrypted data failed\n"));
252 XDR_DESTROY(&temp_xdrs);
253 return FALSE;
254 }
255 out_buf.value = cp;
256
257 *major = gss_release_buffer(minor, &out_buf);
258
259 PRINTF(("gssapi_wrap_data: succeeding\n\n"));
260 XDR_DESTROY(&temp_xdrs);
261 return TRUE;
262 }
263
auth_gssapi_unwrap_data(OM_uint32 * major,OM_uint32 * minor,gss_ctx_id_t context,uint32_t seq_num,XDR * in_xdrs,bool_t (* xdr_func)(),caddr_t xdr_ptr)264 bool_t auth_gssapi_unwrap_data(
265 OM_uint32 *major,
266 OM_uint32 *minor,
267 gss_ctx_id_t context,
268 uint32_t seq_num,
269 XDR *in_xdrs,
270 bool_t (*xdr_func)(),
271 caddr_t xdr_ptr)
272 {
273 gss_buffer_desc in_buf, out_buf;
274 XDR temp_xdrs;
275 uint32_t verf_seq_num;
276 int conf, qop;
277 unsigned int length;
278 char *cp;
279
280 PRINTF(("gssapi_unwrap_data: starting\n"));
281
282 *major = GSS_S_COMPLETE;
283 *minor = 0; /* assumption */
284
285 in_buf.value = NULL;
286 out_buf.value = NULL;
287 cp = in_buf.value;
288 if (! xdr_bytes(in_xdrs, &cp, &length, (unsigned int) -1)) {
289 PRINTF(("gssapi_unwrap_data: deserializing encrypted data failed\n"));
290 temp_xdrs.x_op = XDR_FREE;
291 (void)xdr_bytes(&temp_xdrs, &cp, &length, (unsigned int) -1);
292 in_buf.value = NULL;
293 return FALSE;
294 }
295 in_buf.value = cp;
296 in_buf.length = length;
297
298 *major = gss_unseal(minor, context, &in_buf, &out_buf, &conf,
299 &qop);
300 free(in_buf.value);
301 if (*major != GSS_S_COMPLETE)
302 return FALSE;
303
304 PRINTF(("gssapi_unwrap_data: %llu bytes data, %llu bytes sealed\n",
305 (unsigned long long)out_buf.length,
306 (unsigned long long)in_buf.length));
307
308 xdrmem_create(&temp_xdrs, out_buf.value, out_buf.length, XDR_DECODE);
309
310 /* deserialize the sequence number */
311 if (! xdr_u_int32(&temp_xdrs, &verf_seq_num)) {
312 PRINTF(("gssapi_unwrap_data: deserializing verf_seq_num failed\n"));
313 gss_release_buffer(minor, &out_buf);
314 XDR_DESTROY(&temp_xdrs);
315 return FALSE;
316 }
317 if (verf_seq_num != seq_num) {
318 PRINTF(("gssapi_unwrap_data: seq %d specified, read %d\n",
319 seq_num, verf_seq_num));
320 gss_release_buffer(minor, &out_buf);
321 XDR_DESTROY(&temp_xdrs);
322 return FALSE;
323 }
324 PRINTF(("gssapi_unwrap_data: unwrap seq_num %d okay\n", verf_seq_num));
325
326 /* deserialize the arguments into xdr_ptr */
327 if (! (*xdr_func)(&temp_xdrs, xdr_ptr)) {
328 PRINTF(("gssapi_unwrap_data: deserializing arguments failed\n"));
329 gss_release_buffer(minor, &out_buf);
330 XDR_DESTROY(&temp_xdrs);
331 return FALSE;
332 }
333
334 PRINTF(("gssapi_unwrap_data: succeeding\n\n"));
335
336 gss_release_buffer(minor, &out_buf);
337 XDR_DESTROY(&temp_xdrs);
338 return TRUE;
339 }
340