xref: /freebsd/crypto/krb5/src/lib/rpc/auth_gssapi_misc.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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