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 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 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 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 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 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 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 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 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 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 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