[b376ae1] | 1 | #include <machine/rtems-bsd-user-space.h> |
---|
| 2 | #ifdef __rtems__ |
---|
| 3 | #include <machine/rtems-bsd-program.h> |
---|
| 4 | #include "rtems-bsd-racoon-namespace.h" |
---|
| 5 | #endif /* __rtems__ */ |
---|
| 6 | |
---|
[ff36f5e] | 7 | /* $NetBSD: gssapi.c,v 1.4 2006/09/09 16:22:09 manu Exp $ */ |
---|
| 8 | |
---|
| 9 | /* $KAME: gssapi.c,v 1.19 2001/04/03 15:51:55 thorpej Exp $ */ |
---|
| 10 | |
---|
| 11 | /* |
---|
| 12 | * Copyright 2000 Wasabi Systems, Inc. |
---|
| 13 | * All rights reserved. |
---|
| 14 | * |
---|
| 15 | * This software was written by Frank van der Linden of Wasabi Systems |
---|
| 16 | * for Zembu Labs, Inc. http://www.zembu.com/ |
---|
| 17 | * |
---|
| 18 | * Redistribution and use in source and binary forms, with or without |
---|
| 19 | * modification, are permitted provided that the following conditions |
---|
| 20 | * are met: |
---|
| 21 | * 1. Redistributions of source code must retain the above copyright |
---|
| 22 | * notice, this list of conditions and the following disclaimer. |
---|
| 23 | * 2. Redistributions in binary form must reproduce the above copyright |
---|
| 24 | * notice, this list of conditions and the following disclaimer in the |
---|
| 25 | * documentation and/or other materials provided with the distribution. |
---|
| 26 | * 3. The name of Wasabi Systems, Inc. may not be used to endorse |
---|
| 27 | * or promote products derived from this software without specific prior |
---|
| 28 | * written permission. |
---|
| 29 | * |
---|
| 30 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND |
---|
| 31 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
---|
| 32 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
---|
| 33 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC |
---|
| 34 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
---|
| 35 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
---|
| 36 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
---|
| 37 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
---|
| 38 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
---|
| 39 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
---|
| 40 | * POSSIBILITY OF SUCH DAMAGE. |
---|
| 41 | */ |
---|
| 42 | |
---|
| 43 | #include "config.h" |
---|
| 44 | |
---|
| 45 | #ifdef HAVE_GSSAPI |
---|
| 46 | |
---|
| 47 | #include <sys/types.h> |
---|
| 48 | #include <sys/queue.h> |
---|
| 49 | #include <sys/socket.h> |
---|
| 50 | #include <netdb.h> |
---|
| 51 | #include <unistd.h> |
---|
| 52 | |
---|
| 53 | #include <stdlib.h> |
---|
| 54 | #include <string.h> |
---|
| 55 | #include <errno.h> |
---|
| 56 | |
---|
| 57 | #include "var.h" |
---|
| 58 | #include "misc.h" |
---|
| 59 | #include "vmbuf.h" |
---|
| 60 | #include "plog.h" |
---|
| 61 | #include "sockmisc.h" |
---|
| 62 | #include "schedule.h" |
---|
| 63 | #include "debug.h" |
---|
| 64 | |
---|
| 65 | #include "localconf.h" |
---|
| 66 | #include "remoteconf.h" |
---|
| 67 | #include "isakmp_var.h" |
---|
| 68 | #include "isakmp.h" |
---|
| 69 | #include "oakley.h" |
---|
| 70 | #include "handler.h" |
---|
| 71 | #include "ipsec_doi.h" |
---|
| 72 | #include "crypto_openssl.h" |
---|
| 73 | #include "pfkey.h" |
---|
| 74 | #include "isakmp_ident.h" |
---|
| 75 | #include "isakmp_inf.h" |
---|
| 76 | #include "vendorid.h" |
---|
| 77 | #include "gcmalloc.h" |
---|
| 78 | |
---|
| 79 | #include "gssapi.h" |
---|
| 80 | |
---|
| 81 | static void |
---|
| 82 | gssapi_error(OM_uint32 status_code, const char *where, |
---|
| 83 | const char *fmt, ...) |
---|
| 84 | { |
---|
| 85 | OM_uint32 message_context, maj_stat, min_stat; |
---|
| 86 | gss_buffer_desc status_string; |
---|
| 87 | va_list ap; |
---|
| 88 | |
---|
| 89 | va_start(ap, fmt); |
---|
| 90 | plogv(LLV_ERROR, where, NULL, fmt, ap); |
---|
| 91 | va_end(ap); |
---|
| 92 | |
---|
| 93 | message_context = 0; |
---|
| 94 | |
---|
| 95 | do { |
---|
| 96 | maj_stat = gss_display_status(&min_stat, status_code, |
---|
| 97 | GSS_C_MECH_CODE, GSS_C_NO_OID, &message_context, |
---|
| 98 | &status_string); |
---|
| 99 | if (GSS_ERROR(maj_stat)) |
---|
| 100 | plog(LLV_ERROR, LOCATION, NULL, |
---|
| 101 | "UNABLE TO GET GSSAPI ERROR CODE\n"); |
---|
| 102 | else { |
---|
| 103 | plog(LLV_ERROR, where, NULL, |
---|
| 104 | "%s\n", (char *)status_string.value); |
---|
| 105 | gss_release_buffer(&min_stat, &status_string); |
---|
| 106 | } |
---|
| 107 | } while (message_context != 0); |
---|
| 108 | } |
---|
| 109 | |
---|
| 110 | /* |
---|
| 111 | * vmbufs and gss_buffer_descs are really just the same on NetBSD, but |
---|
| 112 | * this is to be portable. |
---|
| 113 | */ |
---|
| 114 | static int |
---|
| 115 | gssapi_vm2gssbuf(vchar_t *vmbuf, gss_buffer_t gsstoken) |
---|
| 116 | { |
---|
| 117 | |
---|
| 118 | gsstoken->value = racoon_malloc(vmbuf->l); |
---|
| 119 | if (gsstoken->value == NULL) |
---|
| 120 | return -1; |
---|
| 121 | memcpy(gsstoken->value, vmbuf->v, vmbuf->l); |
---|
| 122 | gsstoken->length = vmbuf->l; |
---|
| 123 | |
---|
| 124 | return 0; |
---|
| 125 | } |
---|
| 126 | |
---|
| 127 | static int |
---|
| 128 | gssapi_gss2vmbuf(gss_buffer_t gsstoken, vchar_t **vmbuf) |
---|
| 129 | { |
---|
| 130 | |
---|
| 131 | *vmbuf = vmalloc(gsstoken->length); |
---|
| 132 | if (*vmbuf == NULL) |
---|
| 133 | return -1; |
---|
| 134 | memcpy((*vmbuf)->v, gsstoken->value, gsstoken->length); |
---|
| 135 | (*vmbuf)->l = gsstoken->length; |
---|
| 136 | |
---|
| 137 | return 0; |
---|
| 138 | } |
---|
| 139 | |
---|
| 140 | vchar_t * |
---|
| 141 | gssapi_get_default_gss_id(void) |
---|
| 142 | { |
---|
| 143 | char name[NI_MAXHOST]; |
---|
| 144 | vchar_t *gssid; |
---|
| 145 | |
---|
| 146 | if (gethostname(name, sizeof(name)) != 0) { |
---|
| 147 | plog(LLV_ERROR, LOCATION, NULL, "gethostname failed: %s\n", |
---|
| 148 | strerror(errno)); |
---|
| 149 | return (NULL); |
---|
| 150 | } |
---|
| 151 | name[sizeof(name) - 1] = '\0'; |
---|
| 152 | |
---|
| 153 | gssid = racoon_malloc(sizeof(*gssid)); |
---|
| 154 | gssid->l = asprintf(&gssid->v, "%s/%s", GSSAPI_DEF_NAME, name); |
---|
| 155 | |
---|
| 156 | return (gssid); |
---|
| 157 | } |
---|
| 158 | |
---|
| 159 | static int |
---|
| 160 | gssapi_get_default_name(struct ph1handle *iph1, int remote, gss_name_t *service) |
---|
| 161 | { |
---|
| 162 | char name[NI_MAXHOST]; |
---|
| 163 | struct sockaddr *sa; |
---|
| 164 | char* buf = NULL; |
---|
| 165 | gss_buffer_desc name_token; |
---|
| 166 | OM_uint32 min_stat, maj_stat; |
---|
| 167 | |
---|
| 168 | sa = remote ? iph1->remote : iph1->local; |
---|
| 169 | |
---|
| 170 | if (getnameinfo(sa, sysdep_sa_len(sa), name, NI_MAXHOST, NULL, 0, 0) != 0) |
---|
| 171 | return -1; |
---|
| 172 | |
---|
| 173 | name_token.length = asprintf(&buf, "%s@%s", GSSAPI_DEF_NAME, name); |
---|
| 174 | name_token.value = buf; |
---|
| 175 | |
---|
| 176 | maj_stat = gss_import_name(&min_stat, &name_token, |
---|
| 177 | GSS_C_NT_HOSTBASED_SERVICE, service); |
---|
| 178 | if (GSS_ERROR(maj_stat)) { |
---|
| 179 | gssapi_error(min_stat, LOCATION, "import name\n"); |
---|
| 180 | maj_stat = gss_release_buffer(&min_stat, &name_token); |
---|
| 181 | if (GSS_ERROR(maj_stat)) |
---|
| 182 | gssapi_error(min_stat, LOCATION, "release name_token"); |
---|
| 183 | return -1; |
---|
| 184 | } |
---|
| 185 | maj_stat = gss_release_buffer(&min_stat, &name_token); |
---|
| 186 | if (GSS_ERROR(maj_stat)) |
---|
| 187 | gssapi_error(min_stat, LOCATION, "release name_token"); |
---|
| 188 | |
---|
| 189 | return 0; |
---|
| 190 | } |
---|
| 191 | |
---|
| 192 | static int |
---|
| 193 | gssapi_init(struct ph1handle *iph1) |
---|
| 194 | { |
---|
| 195 | struct gssapi_ph1_state *gps; |
---|
| 196 | gss_buffer_desc id_token, cred_token; |
---|
| 197 | gss_buffer_t cred = &cred_token; |
---|
| 198 | gss_name_t princ, canon_princ; |
---|
| 199 | OM_uint32 maj_stat, min_stat; |
---|
| 200 | |
---|
[8645c9d7] | 201 | if (iph1->rmconf == NULL) { |
---|
| 202 | plog(LLV_ERROR, LOCATION, NULL, "no remote config\n"); |
---|
| 203 | return -1; |
---|
| 204 | } |
---|
| 205 | |
---|
[ff36f5e] | 206 | gps = racoon_calloc(1, sizeof (struct gssapi_ph1_state)); |
---|
| 207 | if (gps == NULL) { |
---|
| 208 | plog(LLV_ERROR, LOCATION, NULL, "racoon_calloc failed\n"); |
---|
| 209 | return -1; |
---|
| 210 | } |
---|
| 211 | gps->gss_context = GSS_C_NO_CONTEXT; |
---|
| 212 | gps->gss_cred = GSS_C_NO_CREDENTIAL; |
---|
| 213 | |
---|
| 214 | gssapi_set_state(iph1, gps); |
---|
| 215 | |
---|
| 216 | if (iph1->rmconf->proposal->gssid != NULL) { |
---|
| 217 | id_token.length = iph1->rmconf->proposal->gssid->l; |
---|
| 218 | id_token.value = iph1->rmconf->proposal->gssid->v; |
---|
| 219 | maj_stat = gss_import_name(&min_stat, &id_token, GSS_C_NO_OID, |
---|
| 220 | &princ); |
---|
| 221 | if (GSS_ERROR(maj_stat)) { |
---|
| 222 | gssapi_error(min_stat, LOCATION, "import name\n"); |
---|
| 223 | gssapi_free_state(iph1); |
---|
| 224 | return -1; |
---|
| 225 | } |
---|
| 226 | } else |
---|
| 227 | gssapi_get_default_name(iph1, 0, &princ); |
---|
| 228 | |
---|
| 229 | maj_stat = gss_canonicalize_name(&min_stat, princ, GSS_C_NO_OID, |
---|
| 230 | &canon_princ); |
---|
| 231 | if (GSS_ERROR(maj_stat)) { |
---|
| 232 | gssapi_error(min_stat, LOCATION, "canonicalize name\n"); |
---|
| 233 | maj_stat = gss_release_name(&min_stat, &princ); |
---|
| 234 | if (GSS_ERROR(maj_stat)) |
---|
| 235 | gssapi_error(min_stat, LOCATION, "release princ\n"); |
---|
| 236 | gssapi_free_state(iph1); |
---|
| 237 | return -1; |
---|
| 238 | } |
---|
| 239 | maj_stat = gss_release_name(&min_stat, &princ); |
---|
| 240 | if (GSS_ERROR(maj_stat)) |
---|
| 241 | gssapi_error(min_stat, LOCATION, "release princ\n"); |
---|
| 242 | |
---|
| 243 | maj_stat = gss_export_name(&min_stat, canon_princ, cred); |
---|
| 244 | if (GSS_ERROR(maj_stat)) { |
---|
| 245 | gssapi_error(min_stat, LOCATION, "export name\n"); |
---|
| 246 | maj_stat = gss_release_name(&min_stat, &canon_princ); |
---|
| 247 | if (GSS_ERROR(maj_stat)) |
---|
| 248 | gssapi_error(min_stat, LOCATION, |
---|
| 249 | "release canon_princ\n"); |
---|
| 250 | gssapi_free_state(iph1); |
---|
| 251 | return -1; |
---|
| 252 | } |
---|
| 253 | |
---|
| 254 | #if 0 |
---|
| 255 | /* |
---|
| 256 | * XXXJRT Did this debug message ever work? This is a GSS name |
---|
| 257 | * blob at this point. |
---|
| 258 | */ |
---|
| 259 | plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s' creds\n", |
---|
| 260 | cred->length, cred->value); |
---|
| 261 | #endif |
---|
| 262 | |
---|
| 263 | maj_stat = gss_release_buffer(&min_stat, cred); |
---|
| 264 | if (GSS_ERROR(maj_stat)) |
---|
| 265 | gssapi_error(min_stat, LOCATION, "release cred buffer\n"); |
---|
| 266 | |
---|
| 267 | maj_stat = gss_acquire_cred(&min_stat, canon_princ, GSS_C_INDEFINITE, |
---|
| 268 | GSS_C_NO_OID_SET, GSS_C_BOTH, &gps->gss_cred, NULL, NULL); |
---|
| 269 | if (GSS_ERROR(maj_stat)) { |
---|
| 270 | gssapi_error(min_stat, LOCATION, "acquire cred\n"); |
---|
| 271 | maj_stat = gss_release_name(&min_stat, &canon_princ); |
---|
| 272 | if (GSS_ERROR(maj_stat)) |
---|
| 273 | gssapi_error(min_stat, LOCATION, |
---|
| 274 | "release canon_princ\n"); |
---|
| 275 | gssapi_free_state(iph1); |
---|
| 276 | return -1; |
---|
| 277 | } |
---|
| 278 | maj_stat = gss_release_name(&min_stat, &canon_princ); |
---|
| 279 | if (GSS_ERROR(maj_stat)) |
---|
| 280 | gssapi_error(min_stat, LOCATION, "release canon_princ\n"); |
---|
| 281 | |
---|
| 282 | return 0; |
---|
| 283 | } |
---|
| 284 | |
---|
| 285 | int |
---|
| 286 | gssapi_get_itoken(struct ph1handle *iph1, int *lenp) |
---|
| 287 | { |
---|
| 288 | struct gssapi_ph1_state *gps; |
---|
| 289 | gss_buffer_desc empty, name_token; |
---|
| 290 | gss_buffer_t itoken, rtoken, dummy; |
---|
| 291 | OM_uint32 maj_stat, min_stat; |
---|
| 292 | gss_name_t partner; |
---|
| 293 | |
---|
| 294 | if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0) |
---|
| 295 | return -1; |
---|
| 296 | |
---|
| 297 | gps = gssapi_get_state(iph1); |
---|
| 298 | |
---|
| 299 | empty.length = 0; |
---|
| 300 | empty.value = NULL; |
---|
| 301 | dummy = ∅ |
---|
| 302 | |
---|
| 303 | if (iph1->approval != NULL && iph1->approval->gssid != NULL) { |
---|
| 304 | plog(LLV_DEBUG, LOCATION, NULL, |
---|
| 305 | "using provided service '%.*s'\n", |
---|
| 306 | (int)iph1->approval->gssid->l, iph1->approval->gssid->v); |
---|
| 307 | name_token.length = iph1->approval->gssid->l; |
---|
| 308 | name_token.value = iph1->approval->gssid->v; |
---|
| 309 | maj_stat = gss_import_name(&min_stat, &name_token, |
---|
| 310 | GSS_C_NO_OID, &partner); |
---|
| 311 | if (GSS_ERROR(maj_stat)) { |
---|
| 312 | gssapi_error(min_stat, LOCATION, "import of %.*s\n", |
---|
| 313 | name_token.length, name_token.value); |
---|
| 314 | return -1; |
---|
| 315 | } |
---|
| 316 | } else |
---|
| 317 | if (gssapi_get_default_name(iph1, 1, &partner) < 0) |
---|
| 318 | return -1; |
---|
| 319 | |
---|
| 320 | rtoken = gps->gsscnt_p == 0 ? dummy : &gps->gss_p[gps->gsscnt_p - 1]; |
---|
| 321 | itoken = &gps->gss[gps->gsscnt]; |
---|
| 322 | |
---|
| 323 | gps->gss_status = gss_init_sec_context(&min_stat, gps->gss_cred, |
---|
| 324 | &gps->gss_context, partner, GSS_C_NO_OID, |
---|
| 325 | GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG | |
---|
| 326 | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG, |
---|
| 327 | 0, GSS_C_NO_CHANNEL_BINDINGS, rtoken, NULL, |
---|
| 328 | itoken, NULL, NULL); |
---|
| 329 | |
---|
| 330 | if (GSS_ERROR(gps->gss_status)) { |
---|
| 331 | gssapi_error(min_stat, LOCATION, "init_sec_context\n"); |
---|
| 332 | maj_stat = gss_release_name(&min_stat, &partner); |
---|
| 333 | if (GSS_ERROR(maj_stat)) |
---|
| 334 | gssapi_error(min_stat, LOCATION, "release name\n"); |
---|
| 335 | return -1; |
---|
| 336 | } |
---|
| 337 | maj_stat = gss_release_name(&min_stat, &partner); |
---|
| 338 | if (GSS_ERROR(maj_stat)) |
---|
| 339 | gssapi_error(min_stat, LOCATION, "release name\n"); |
---|
| 340 | |
---|
| 341 | plog(LLV_DEBUG, LOCATION, NULL, "gss_init_sec_context status %x\n", |
---|
| 342 | gps->gss_status); |
---|
| 343 | |
---|
| 344 | if (lenp) |
---|
| 345 | *lenp = itoken->length; |
---|
| 346 | |
---|
| 347 | if (itoken->length != 0) |
---|
| 348 | gps->gsscnt++; |
---|
| 349 | |
---|
| 350 | return 0; |
---|
| 351 | } |
---|
| 352 | |
---|
| 353 | /* |
---|
| 354 | * Call gss_accept_context, with token just read from the wire. |
---|
| 355 | */ |
---|
| 356 | int |
---|
| 357 | gssapi_get_rtoken(struct ph1handle *iph1, int *lenp) |
---|
| 358 | { |
---|
| 359 | struct gssapi_ph1_state *gps; |
---|
| 360 | gss_buffer_desc name_token; |
---|
| 361 | gss_buffer_t itoken, rtoken; |
---|
| 362 | OM_uint32 min_stat, maj_stat; |
---|
| 363 | gss_name_t client_name; |
---|
| 364 | |
---|
| 365 | if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0) |
---|
| 366 | return -1; |
---|
| 367 | |
---|
| 368 | gps = gssapi_get_state(iph1); |
---|
| 369 | |
---|
| 370 | rtoken = &gps->gss_p[gps->gsscnt_p - 1]; |
---|
| 371 | itoken = &gps->gss[gps->gsscnt]; |
---|
| 372 | |
---|
| 373 | gps->gss_status = gss_accept_sec_context(&min_stat, &gps->gss_context, |
---|
| 374 | gps->gss_cred, rtoken, GSS_C_NO_CHANNEL_BINDINGS, &client_name, |
---|
| 375 | NULL, itoken, NULL, NULL, NULL); |
---|
| 376 | |
---|
| 377 | if (GSS_ERROR(gps->gss_status)) { |
---|
| 378 | gssapi_error(min_stat, LOCATION, "accept_sec_context\n"); |
---|
| 379 | return -1; |
---|
| 380 | } |
---|
| 381 | |
---|
| 382 | maj_stat = gss_display_name(&min_stat, client_name, &name_token, NULL); |
---|
| 383 | if (GSS_ERROR(maj_stat)) { |
---|
| 384 | gssapi_error(min_stat, LOCATION, "gss_display_name\n"); |
---|
| 385 | maj_stat = gss_release_name(&min_stat, &client_name); |
---|
| 386 | if (GSS_ERROR(maj_stat)) |
---|
| 387 | gssapi_error(min_stat, LOCATION, |
---|
| 388 | "release client_name\n"); |
---|
| 389 | return -1; |
---|
| 390 | } |
---|
| 391 | maj_stat = gss_release_name(&min_stat, &client_name); |
---|
| 392 | if (GSS_ERROR(maj_stat)) |
---|
| 393 | gssapi_error(min_stat, LOCATION, "release client_name\n"); |
---|
| 394 | |
---|
| 395 | plog(LLV_DEBUG, LOCATION, NULL, |
---|
| 396 | "gss_accept_sec_context: other side is %s\n", |
---|
| 397 | (char *)name_token.value); |
---|
| 398 | maj_stat = gss_release_buffer(&min_stat, &name_token); |
---|
| 399 | if (GSS_ERROR(maj_stat)) |
---|
| 400 | gssapi_error(min_stat, LOCATION, "release name buffer\n"); |
---|
| 401 | |
---|
| 402 | if (itoken->length != 0) |
---|
| 403 | gps->gsscnt++; |
---|
| 404 | |
---|
| 405 | if (lenp) |
---|
| 406 | *lenp = itoken->length; |
---|
| 407 | |
---|
| 408 | return 0; |
---|
| 409 | } |
---|
| 410 | |
---|
| 411 | int |
---|
| 412 | gssapi_save_received_token(struct ph1handle *iph1, vchar_t *token) |
---|
| 413 | { |
---|
| 414 | struct gssapi_ph1_state *gps; |
---|
| 415 | gss_buffer_t gsstoken; |
---|
| 416 | int ret; |
---|
| 417 | |
---|
| 418 | if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0) |
---|
| 419 | return -1; |
---|
| 420 | |
---|
| 421 | gps = gssapi_get_state(iph1); |
---|
| 422 | |
---|
| 423 | gsstoken = &gps->gss_p[gps->gsscnt_p]; |
---|
| 424 | |
---|
| 425 | ret = gssapi_vm2gssbuf(token, gsstoken); |
---|
| 426 | if (ret < 0) |
---|
| 427 | return ret; |
---|
| 428 | gps->gsscnt_p++; |
---|
| 429 | |
---|
| 430 | return 0; |
---|
| 431 | } |
---|
| 432 | |
---|
| 433 | int |
---|
| 434 | gssapi_get_token_to_send(struct ph1handle *iph1, vchar_t **token) |
---|
| 435 | { |
---|
| 436 | struct gssapi_ph1_state *gps; |
---|
| 437 | gss_buffer_t gsstoken; |
---|
| 438 | int ret; |
---|
| 439 | |
---|
| 440 | gps = gssapi_get_state(iph1); |
---|
| 441 | if (gps == NULL) { |
---|
| 442 | plog(LLV_ERROR, LOCATION, NULL, |
---|
| 443 | "gssapi not yet initialized?\n"); |
---|
| 444 | return -1; |
---|
| 445 | } |
---|
| 446 | gsstoken = &gps->gss[gps->gsscnt - 1]; |
---|
| 447 | ret = gssapi_gss2vmbuf(gsstoken, token); |
---|
| 448 | if (ret < 0) |
---|
| 449 | return ret; |
---|
| 450 | |
---|
| 451 | return 0; |
---|
| 452 | } |
---|
| 453 | |
---|
| 454 | int |
---|
| 455 | gssapi_get_itokens(struct ph1handle *iph1, vchar_t **tokens) |
---|
| 456 | { |
---|
| 457 | struct gssapi_ph1_state *gps; |
---|
| 458 | int len, i; |
---|
| 459 | vchar_t *toks; |
---|
| 460 | char *p; |
---|
| 461 | |
---|
| 462 | gps = gssapi_get_state(iph1); |
---|
| 463 | if (gps == NULL) { |
---|
| 464 | plog(LLV_ERROR, LOCATION, NULL, |
---|
| 465 | "gssapi not yet initialized?\n"); |
---|
| 466 | return -1; |
---|
| 467 | } |
---|
| 468 | |
---|
| 469 | for (i = len = 0; i < gps->gsscnt; i++) |
---|
| 470 | len += gps->gss[i].length; |
---|
| 471 | |
---|
| 472 | toks = vmalloc(len); |
---|
| 473 | if (toks == 0) |
---|
| 474 | return -1; |
---|
| 475 | p = (char *)toks->v; |
---|
| 476 | for (i = 0; i < gps->gsscnt; i++) { |
---|
| 477 | memcpy(p, gps->gss[i].value, gps->gss[i].length); |
---|
| 478 | p += gps->gss[i].length; |
---|
| 479 | } |
---|
| 480 | |
---|
| 481 | *tokens = toks; |
---|
| 482 | |
---|
| 483 | plog(LLV_DEBUG, LOCATION, NULL, |
---|
| 484 | "%d itokens of length %zu\n", gps->gsscnt, (*tokens)->l); |
---|
| 485 | |
---|
| 486 | return 0; |
---|
| 487 | } |
---|
| 488 | |
---|
| 489 | int |
---|
| 490 | gssapi_get_rtokens(struct ph1handle *iph1, vchar_t **tokens) |
---|
| 491 | { |
---|
| 492 | struct gssapi_ph1_state *gps; |
---|
| 493 | int len, i; |
---|
| 494 | vchar_t *toks; |
---|
| 495 | char *p; |
---|
| 496 | |
---|
| 497 | gps = gssapi_get_state(iph1); |
---|
| 498 | if (gps == NULL) { |
---|
| 499 | plog(LLV_ERROR, LOCATION, NULL, |
---|
| 500 | "gssapi not yet initialized?\n"); |
---|
| 501 | return -1; |
---|
| 502 | } |
---|
| 503 | |
---|
| 504 | if (gssapi_more_tokens(iph1)) { |
---|
| 505 | plog(LLV_ERROR, LOCATION, NULL, |
---|
| 506 | "gssapi roundtrips not complete\n"); |
---|
| 507 | return -1; |
---|
| 508 | } |
---|
| 509 | |
---|
| 510 | for (i = len = 0; i < gps->gsscnt_p; i++) |
---|
| 511 | len += gps->gss_p[i].length; |
---|
| 512 | |
---|
| 513 | toks = vmalloc(len); |
---|
| 514 | if (toks == 0) |
---|
| 515 | return -1; |
---|
| 516 | p = (char *)toks->v; |
---|
| 517 | for (i = 0; i < gps->gsscnt_p; i++) { |
---|
| 518 | memcpy(p, gps->gss_p[i].value, gps->gss_p[i].length); |
---|
| 519 | p += gps->gss_p[i].length; |
---|
| 520 | } |
---|
| 521 | |
---|
| 522 | *tokens = toks; |
---|
| 523 | |
---|
| 524 | return 0; |
---|
| 525 | } |
---|
| 526 | |
---|
| 527 | vchar_t * |
---|
| 528 | gssapi_wraphash(struct ph1handle *iph1) |
---|
| 529 | { |
---|
| 530 | struct gssapi_ph1_state *gps; |
---|
| 531 | OM_uint32 maj_stat, min_stat; |
---|
| 532 | gss_buffer_desc hash_in_buf, hash_out_buf; |
---|
| 533 | gss_buffer_t hash_in = &hash_in_buf, hash_out = &hash_out_buf; |
---|
| 534 | vchar_t *outbuf; |
---|
| 535 | |
---|
| 536 | gps = gssapi_get_state(iph1); |
---|
| 537 | if (gps == NULL) { |
---|
| 538 | plog(LLV_ERROR, LOCATION, NULL, |
---|
| 539 | "gssapi not yet initialized?\n"); |
---|
| 540 | return NULL; |
---|
| 541 | } |
---|
| 542 | |
---|
| 543 | if (gssapi_more_tokens(iph1)) { |
---|
| 544 | plog(LLV_ERROR, LOCATION, NULL, |
---|
| 545 | "gssapi roundtrips not complete\n"); |
---|
| 546 | return NULL; |
---|
| 547 | } |
---|
| 548 | |
---|
| 549 | if (gssapi_vm2gssbuf(iph1->hash, hash_in) < 0) { |
---|
| 550 | plog(LLV_ERROR, LOCATION, NULL, "vm2gssbuf failed\n"); |
---|
| 551 | return NULL; |
---|
| 552 | } |
---|
| 553 | |
---|
| 554 | maj_stat = gss_wrap(&min_stat, gps->gss_context, 1, GSS_C_QOP_DEFAULT, |
---|
| 555 | hash_in, NULL, hash_out); |
---|
| 556 | if (GSS_ERROR(maj_stat)) { |
---|
| 557 | gssapi_error(min_stat, LOCATION, "wrapping hash value\n"); |
---|
| 558 | maj_stat = gss_release_buffer(&min_stat, hash_in); |
---|
| 559 | if (GSS_ERROR(maj_stat)) |
---|
| 560 | gssapi_error(min_stat, LOCATION, |
---|
| 561 | "release hash_in buffer\n"); |
---|
| 562 | return NULL; |
---|
| 563 | } |
---|
| 564 | |
---|
| 565 | plog(LLV_DEBUG, LOCATION, NULL, "wrapped HASH, ilen %zu olen %zu\n", |
---|
| 566 | hash_in->length, hash_out->length); |
---|
| 567 | |
---|
| 568 | maj_stat = gss_release_buffer(&min_stat, hash_in); |
---|
| 569 | if (GSS_ERROR(maj_stat)) |
---|
| 570 | gssapi_error(min_stat, LOCATION, "release hash_in buffer\n"); |
---|
| 571 | |
---|
| 572 | if (gssapi_gss2vmbuf(hash_out, &outbuf) < 0) { |
---|
| 573 | plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n"); |
---|
| 574 | maj_stat = gss_release_buffer(&min_stat, hash_out); |
---|
| 575 | if (GSS_ERROR(maj_stat)) |
---|
| 576 | gssapi_error(min_stat, LOCATION, |
---|
| 577 | "release hash_out buffer\n"); |
---|
| 578 | return NULL; |
---|
| 579 | } |
---|
| 580 | maj_stat = gss_release_buffer(&min_stat, hash_out); |
---|
| 581 | if (GSS_ERROR(maj_stat)) |
---|
| 582 | gssapi_error(min_stat, LOCATION, "release hash_out buffer\n"); |
---|
| 583 | |
---|
| 584 | return outbuf; |
---|
| 585 | } |
---|
| 586 | |
---|
| 587 | vchar_t * |
---|
| 588 | gssapi_unwraphash(struct ph1handle *iph1) |
---|
| 589 | { |
---|
| 590 | struct gssapi_ph1_state *gps; |
---|
| 591 | OM_uint32 maj_stat, min_stat; |
---|
| 592 | gss_buffer_desc hashbuf, hash_outbuf; |
---|
| 593 | gss_buffer_t hash_in = &hashbuf, hash_out = &hash_outbuf; |
---|
| 594 | vchar_t *outbuf; |
---|
| 595 | |
---|
| 596 | gps = gssapi_get_state(iph1); |
---|
| 597 | if (gps == NULL) { |
---|
| 598 | plog(LLV_ERROR, LOCATION, NULL, |
---|
| 599 | "gssapi not yet initialized?\n"); |
---|
| 600 | return NULL; |
---|
| 601 | } |
---|
| 602 | |
---|
| 603 | |
---|
| 604 | hashbuf.length = ntohs(iph1->pl_hash->h.len) - sizeof(*iph1->pl_hash); |
---|
| 605 | hashbuf.value = (char *)(iph1->pl_hash + 1); |
---|
| 606 | |
---|
| 607 | plog(LLV_DEBUG, LOCATION, NULL, "unwrapping HASH of len %zu\n", |
---|
| 608 | hashbuf.length); |
---|
| 609 | |
---|
| 610 | maj_stat = gss_unwrap(&min_stat, gps->gss_context, hash_in, hash_out, |
---|
| 611 | NULL, NULL); |
---|
| 612 | if (GSS_ERROR(maj_stat)) { |
---|
| 613 | gssapi_error(min_stat, LOCATION, "unwrapping hash value\n"); |
---|
| 614 | return NULL; |
---|
| 615 | } |
---|
| 616 | |
---|
| 617 | if (gssapi_gss2vmbuf(hash_out, &outbuf) < 0) { |
---|
| 618 | plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n"); |
---|
| 619 | maj_stat = gss_release_buffer(&min_stat, hash_out); |
---|
| 620 | if (GSS_ERROR(maj_stat)) |
---|
| 621 | gssapi_error(min_stat, LOCATION, |
---|
| 622 | "release hash_out buffer\n"); |
---|
| 623 | return NULL; |
---|
| 624 | } |
---|
| 625 | maj_stat = gss_release_buffer(&min_stat, hash_out); |
---|
| 626 | if (GSS_ERROR(maj_stat)) |
---|
| 627 | gssapi_error(min_stat, LOCATION, "release hash_out buffer\n"); |
---|
| 628 | |
---|
| 629 | return outbuf; |
---|
| 630 | } |
---|
| 631 | |
---|
| 632 | void |
---|
| 633 | gssapi_set_id_sent(struct ph1handle *iph1) |
---|
| 634 | { |
---|
| 635 | struct gssapi_ph1_state *gps; |
---|
| 636 | |
---|
| 637 | gps = gssapi_get_state(iph1); |
---|
| 638 | |
---|
| 639 | gps->gss_flags |= GSSFLAG_ID_SENT; |
---|
| 640 | } |
---|
| 641 | |
---|
| 642 | int |
---|
| 643 | gssapi_id_sent(struct ph1handle *iph1) |
---|
| 644 | { |
---|
| 645 | struct gssapi_ph1_state *gps; |
---|
| 646 | |
---|
| 647 | gps = gssapi_get_state(iph1); |
---|
| 648 | |
---|
| 649 | return (gps->gss_flags & GSSFLAG_ID_SENT) != 0; |
---|
| 650 | } |
---|
| 651 | |
---|
| 652 | void |
---|
| 653 | gssapi_set_id_rcvd(struct ph1handle *iph1) |
---|
| 654 | { |
---|
| 655 | struct gssapi_ph1_state *gps; |
---|
| 656 | |
---|
| 657 | gps = gssapi_get_state(iph1); |
---|
| 658 | |
---|
| 659 | gps->gss_flags |= GSSFLAG_ID_RCVD; |
---|
| 660 | } |
---|
| 661 | |
---|
| 662 | int |
---|
| 663 | gssapi_id_rcvd(struct ph1handle *iph1) |
---|
| 664 | { |
---|
| 665 | struct gssapi_ph1_state *gps; |
---|
| 666 | |
---|
| 667 | gps = gssapi_get_state(iph1); |
---|
| 668 | |
---|
| 669 | return (gps->gss_flags & GSSFLAG_ID_RCVD) != 0; |
---|
| 670 | } |
---|
| 671 | |
---|
| 672 | void |
---|
| 673 | gssapi_free_state(struct ph1handle *iph1) |
---|
| 674 | { |
---|
| 675 | struct gssapi_ph1_state *gps; |
---|
| 676 | OM_uint32 maj_stat, min_stat; |
---|
| 677 | |
---|
| 678 | gps = gssapi_get_state(iph1); |
---|
| 679 | |
---|
| 680 | if (gps == NULL) |
---|
| 681 | return; |
---|
| 682 | |
---|
| 683 | gssapi_set_state(iph1, NULL); |
---|
| 684 | |
---|
| 685 | if (gps->gss_cred != GSS_C_NO_CREDENTIAL) { |
---|
| 686 | maj_stat = gss_release_cred(&min_stat, &gps->gss_cred); |
---|
| 687 | if (GSS_ERROR(maj_stat)) |
---|
| 688 | gssapi_error(min_stat, LOCATION, |
---|
| 689 | "releasing credentials\n"); |
---|
| 690 | } |
---|
| 691 | racoon_free(gps); |
---|
| 692 | } |
---|
| 693 | |
---|
| 694 | vchar_t * |
---|
| 695 | gssapi_get_id(struct ph1handle *iph1) |
---|
| 696 | { |
---|
| 697 | gss_buffer_desc id_buffer; |
---|
| 698 | gss_buffer_t id = &id_buffer; |
---|
| 699 | gss_name_t defname, canon_name; |
---|
| 700 | OM_uint32 min_stat, maj_stat; |
---|
| 701 | vchar_t *vmbuf; |
---|
| 702 | |
---|
| 703 | if (iph1->rmconf->proposal->gssid != NULL) |
---|
| 704 | return (vdup(iph1->rmconf->proposal->gssid)); |
---|
| 705 | |
---|
| 706 | if (gssapi_get_default_name(iph1, 0, &defname) < 0) |
---|
| 707 | return NULL; |
---|
| 708 | |
---|
| 709 | maj_stat = gss_canonicalize_name(&min_stat, defname, GSS_C_NO_OID, |
---|
| 710 | &canon_name); |
---|
| 711 | if (GSS_ERROR(maj_stat)) { |
---|
| 712 | gssapi_error(min_stat, LOCATION, "canonicalize name\n"); |
---|
| 713 | maj_stat = gss_release_name(&min_stat, &defname); |
---|
| 714 | if (GSS_ERROR(maj_stat)) |
---|
| 715 | gssapi_error(min_stat, LOCATION, |
---|
| 716 | "release default name\n"); |
---|
| 717 | return NULL; |
---|
| 718 | } |
---|
| 719 | maj_stat = gss_release_name(&min_stat, &defname); |
---|
| 720 | if (GSS_ERROR(maj_stat)) |
---|
| 721 | gssapi_error(min_stat, LOCATION, "release default name\n"); |
---|
| 722 | |
---|
| 723 | maj_stat = gss_export_name(&min_stat, canon_name, id); |
---|
| 724 | if (GSS_ERROR(maj_stat)) { |
---|
| 725 | gssapi_error(min_stat, LOCATION, "export name\n"); |
---|
| 726 | maj_stat = gss_release_name(&min_stat, &canon_name); |
---|
| 727 | if (GSS_ERROR(maj_stat)) |
---|
| 728 | gssapi_error(min_stat, LOCATION, |
---|
| 729 | "release canonical name\n"); |
---|
| 730 | return NULL; |
---|
| 731 | } |
---|
| 732 | maj_stat = gss_release_name(&min_stat, &canon_name); |
---|
| 733 | if (GSS_ERROR(maj_stat)) |
---|
| 734 | gssapi_error(min_stat, LOCATION, "release canonical name\n"); |
---|
| 735 | |
---|
| 736 | #if 0 |
---|
| 737 | /* |
---|
| 738 | * XXXJRT Did this debug message ever work? This is a GSS name |
---|
| 739 | * blob at this point. |
---|
| 740 | */ |
---|
| 741 | plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s' creds\n", |
---|
| 742 | id->length, id->value); |
---|
| 743 | #endif |
---|
| 744 | |
---|
| 745 | if (gssapi_gss2vmbuf(id, &vmbuf) < 0) { |
---|
| 746 | plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n"); |
---|
| 747 | maj_stat = gss_release_buffer(&min_stat, id); |
---|
| 748 | if (GSS_ERROR(maj_stat)) |
---|
| 749 | gssapi_error(min_stat, LOCATION, "release id buffer\n"); |
---|
| 750 | return NULL; |
---|
| 751 | } |
---|
| 752 | maj_stat = gss_release_buffer(&min_stat, id); |
---|
| 753 | if (GSS_ERROR(maj_stat)) |
---|
| 754 | gssapi_error(min_stat, LOCATION, "release id buffer\n"); |
---|
| 755 | |
---|
| 756 | return vmbuf; |
---|
| 757 | } |
---|
| 758 | #else |
---|
| 759 | int __gssapi_dUmMy; |
---|
| 760 | #endif |
---|
[b376ae1] | 761 | #ifdef __rtems__ |
---|
| 762 | #include "rtems-bsd-racoon-gssapi-data.h" |
---|
| 763 | #endif /* __rtems__ */ |
---|