1 /*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)spx.c 8.1 (Berkeley) 06/04/93"; 10 #endif /* not lint */ 11 12 #ifdef SPX 13 /* 14 * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION 15 * ALL RIGHTS RESERVED 16 * 17 * "Digital Equipment Corporation authorizes the reproduction, 18 * distribution and modification of this software subject to the following 19 * restrictions: 20 * 21 * 1. Any partial or whole copy of this software, or any modification 22 * thereof, must include this copyright notice in its entirety. 23 * 24 * 2. This software is supplied "as is" with no warranty of any kind, 25 * expressed or implied, for any purpose, including any warranty of fitness 26 * or merchantibility. DIGITAL assumes no responsibility for the use or 27 * reliability of this software, nor promises to provide any form of 28 * support for it on any basis. 29 * 30 * 3. Distribution of this software is authorized only if no profit or 31 * remuneration of any kind is received in exchange for such distribution. 32 * 33 * 4. This software produces public key authentication certificates 34 * bearing an expiration date established by DIGITAL and RSA Data 35 * Security, Inc. It may cease to generate certificates after the expiration 36 * date. Any modification of this software that changes or defeats 37 * the expiration date or its effect is unauthorized. 38 * 39 * 5. Software that will renew or extend the expiration date of 40 * authentication certificates produced by this software may be obtained 41 * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA 42 * 94065, (415)595-8782, or from DIGITAL" 43 * 44 */ 45 46 #include <sys/types.h> 47 #include <arpa/telnet.h> 48 #include <stdio.h> 49 #include "gssapi_defs.h" 50 #ifdef __STDC__ 51 #include <stdlib.h> 52 #endif 53 #ifdef NO_STRING_H 54 #include <strings.h> 55 #else 56 #include <string.h> 57 #endif 58 59 #include <pwd.h> 60 #include "encrypt.h" 61 #include "auth.h" 62 #include "misc.h" 63 64 extern auth_debug_mode; 65 66 static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, 67 AUTHTYPE_SPX, }; 68 static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 69 TELQUAL_NAME, }; 70 71 #define SPX_AUTH 0 /* Authentication data follows */ 72 #define SPX_REJECT 1 /* Rejected (reason might follow) */ 73 #define SPX_ACCEPT 2 /* Accepted */ 74 75 #ifdef ENCRYPTION 76 static Block session_key = { 0 }; 77 #endif /* ENCRYPTION */ 78 static Schedule sched; 79 static Block challenge = { 0 }; 80 81 82 /*******************************************************************/ 83 84 gss_OID_set actual_mechs; 85 gss_OID actual_mech_type, output_name_type; 86 int major_status, status, msg_ctx = 0, new_status; 87 int req_flags = 0, ret_flags, lifetime_rec; 88 gss_cred_id_t gss_cred_handle; 89 gss_ctx_id_t actual_ctxhandle, context_handle; 90 gss_buffer_desc output_token, input_token, input_name_buffer; 91 gss_buffer_desc status_string; 92 gss_name_t desired_targname, src_name; 93 gss_channel_bindings input_chan_bindings; 94 char lhostname[GSS_C_MAX_PRINTABLE_NAME]; 95 char targ_printable[GSS_C_MAX_PRINTABLE_NAME]; 96 int to_addr=0, from_addr=0; 97 char *address; 98 gss_buffer_desc fullname_buffer; 99 gss_OID fullname_type; 100 gss_cred_id_t gss_delegated_cred_handle; 101 102 /*******************************************************************/ 103 104 105 106 static int 107 Data(ap, type, d, c) 108 Authenticator *ap; 109 int type; 110 void *d; 111 int c; 112 { 113 unsigned char *p = str_data + 4; 114 unsigned char *cd = (unsigned char *)d; 115 116 if (c == -1) 117 c = strlen((char *)cd); 118 119 if (0) { 120 printf("%s:%d: [%d] (%d)", 121 str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", 122 str_data[3], 123 type, c); 124 printd(d, c); 125 printf("\r\n"); 126 } 127 *p++ = ap->type; 128 *p++ = ap->way; 129 *p++ = type; 130 while (c-- > 0) { 131 if ((*p++ = *cd++) == IAC) 132 *p++ = IAC; 133 } 134 *p++ = IAC; 135 *p++ = SE; 136 if (str_data[3] == TELQUAL_IS) 137 printsub('>', &str_data[2], p - (&str_data[2])); 138 return(net_write(str_data, p - str_data)); 139 } 140 141 int 142 spx_init(ap, server) 143 Authenticator *ap; 144 int server; 145 { 146 gss_cred_id_t tmp_cred_handle; 147 148 if (server) { 149 str_data[3] = TELQUAL_REPLY; 150 gethostname(lhostname, sizeof(lhostname)); 151 strcpy(targ_printable, "SERVICE:rcmd@"); 152 strcat(targ_printable, lhostname); 153 input_name_buffer.length = strlen(targ_printable); 154 input_name_buffer.value = targ_printable; 155 major_status = gss_import_name(&status, 156 &input_name_buffer, 157 GSS_C_NULL_OID, 158 &desired_targname); 159 major_status = gss_acquire_cred(&status, 160 desired_targname, 161 0, 162 GSS_C_NULL_OID_SET, 163 GSS_C_ACCEPT, 164 &tmp_cred_handle, 165 &actual_mechs, 166 &lifetime_rec); 167 if (major_status != GSS_S_COMPLETE) return(0); 168 } else { 169 str_data[3] = TELQUAL_IS; 170 } 171 return(1); 172 } 173 174 int 175 spx_send(ap) 176 Authenticator *ap; 177 { 178 Block enckey; 179 int r; 180 181 gss_OID actual_mech_type, output_name_type; 182 int msg_ctx = 0, new_status, status; 183 int req_flags = 0, ret_flags, lifetime_rec, major_status; 184 gss_buffer_desc output_token, input_token, input_name_buffer; 185 gss_buffer_desc output_name_buffer, status_string; 186 gss_name_t desired_targname; 187 gss_channel_bindings input_chan_bindings; 188 char targ_printable[GSS_C_MAX_PRINTABLE_NAME]; 189 int from_addr=0, to_addr=0, myhostlen, j; 190 int deleg_flag=1, mutual_flag=0, replay_flag=0, seq_flag=0; 191 char *address; 192 193 printf("[ Trying SPX ... ]\n"); 194 strcpy(targ_printable, "SERVICE:rcmd@"); 195 strcat(targ_printable, RemoteHostName); 196 197 input_name_buffer.length = strlen(targ_printable); 198 input_name_buffer.value = targ_printable; 199 200 if (!UserNameRequested) { 201 return(0); 202 } 203 204 major_status = gss_import_name(&status, 205 &input_name_buffer, 206 GSS_C_NULL_OID, 207 &desired_targname); 208 209 210 major_status = gss_display_name(&status, 211 desired_targname, 212 &output_name_buffer, 213 &output_name_type); 214 215 printf("target is '%s'\n", output_name_buffer.value); fflush(stdout); 216 217 major_status = gss_release_buffer(&status, &output_name_buffer); 218 219 input_chan_bindings = (gss_channel_bindings) 220 malloc(sizeof(gss_channel_bindings_desc)); 221 222 input_chan_bindings->initiator_addrtype = GSS_C_AF_INET; 223 input_chan_bindings->initiator_address.length = 4; 224 address = (char *) malloc(4); 225 input_chan_bindings->initiator_address.value = (char *) address; 226 address[0] = ((from_addr & 0xff000000) >> 24); 227 address[1] = ((from_addr & 0xff0000) >> 16); 228 address[2] = ((from_addr & 0xff00) >> 8); 229 address[3] = (from_addr & 0xff); 230 input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET; 231 input_chan_bindings->acceptor_address.length = 4; 232 address = (char *) malloc(4); 233 input_chan_bindings->acceptor_address.value = (char *) address; 234 address[0] = ((to_addr & 0xff000000) >> 24); 235 address[1] = ((to_addr & 0xff0000) >> 16); 236 address[2] = ((to_addr & 0xff00) >> 8); 237 address[3] = (to_addr & 0xff); 238 input_chan_bindings->application_data.length = 0; 239 240 req_flags = 0; 241 if (deleg_flag) req_flags = req_flags | 1; 242 if (mutual_flag) req_flags = req_flags | 2; 243 if (replay_flag) req_flags = req_flags | 4; 244 if (seq_flag) req_flags = req_flags | 8; 245 246 major_status = gss_init_sec_context(&status, /* minor status */ 247 GSS_C_NO_CREDENTIAL, /* cred handle */ 248 &actual_ctxhandle, /* ctx handle */ 249 desired_targname, /* target name */ 250 GSS_C_NULL_OID, /* mech type */ 251 req_flags, /* req flags */ 252 0, /* time req */ 253 input_chan_bindings, /* chan binding */ 254 GSS_C_NO_BUFFER, /* input token */ 255 &actual_mech_type, /* actual mech */ 256 &output_token, /* output token */ 257 &ret_flags, /* ret flags */ 258 &lifetime_rec); /* time rec */ 259 260 if ((major_status != GSS_S_COMPLETE) && 261 (major_status != GSS_S_CONTINUE_NEEDED)) { 262 gss_display_status(&new_status, 263 status, 264 GSS_C_MECH_CODE, 265 GSS_C_NULL_OID, 266 &msg_ctx, 267 &status_string); 268 printf("%s\n", status_string.value); 269 return(0); 270 } 271 272 if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { 273 return(0); 274 } 275 276 if (!Data(ap, SPX_AUTH, (void *)output_token.value, output_token.length)) { 277 return(0); 278 } 279 280 return(1); 281 } 282 283 void 284 spx_is(ap, data, cnt) 285 Authenticator *ap; 286 unsigned char *data; 287 int cnt; 288 { 289 Session_Key skey; 290 Block datablock; 291 int r; 292 293 if (cnt-- < 1) 294 return; 295 switch (*data++) { 296 case SPX_AUTH: 297 input_token.length = cnt; 298 input_token.value = (char *) data; 299 300 gethostname(lhostname, sizeof(lhostname)); 301 302 strcpy(targ_printable, "SERVICE:rcmd@"); 303 strcat(targ_printable, lhostname); 304 305 input_name_buffer.length = strlen(targ_printable); 306 input_name_buffer.value = targ_printable; 307 308 major_status = gss_import_name(&status, 309 &input_name_buffer, 310 GSS_C_NULL_OID, 311 &desired_targname); 312 313 major_status = gss_acquire_cred(&status, 314 desired_targname, 315 0, 316 GSS_C_NULL_OID_SET, 317 GSS_C_ACCEPT, 318 &gss_cred_handle, 319 &actual_mechs, 320 &lifetime_rec); 321 322 major_status = gss_release_name(&status, desired_targname); 323 324 input_chan_bindings = (gss_channel_bindings) 325 malloc(sizeof(gss_channel_bindings_desc)); 326 327 input_chan_bindings->initiator_addrtype = GSS_C_AF_INET; 328 input_chan_bindings->initiator_address.length = 4; 329 address = (char *) malloc(4); 330 input_chan_bindings->initiator_address.value = (char *) address; 331 address[0] = ((from_addr & 0xff000000) >> 24); 332 address[1] = ((from_addr & 0xff0000) >> 16); 333 address[2] = ((from_addr & 0xff00) >> 8); 334 address[3] = (from_addr & 0xff); 335 input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET; 336 input_chan_bindings->acceptor_address.length = 4; 337 address = (char *) malloc(4); 338 input_chan_bindings->acceptor_address.value = (char *) address; 339 address[0] = ((to_addr & 0xff000000) >> 24); 340 address[1] = ((to_addr & 0xff0000) >> 16); 341 address[2] = ((to_addr & 0xff00) >> 8); 342 address[3] = (to_addr & 0xff); 343 input_chan_bindings->application_data.length = 0; 344 345 major_status = gss_accept_sec_context(&status, 346 &context_handle, 347 gss_cred_handle, 348 &input_token, 349 input_chan_bindings, 350 &src_name, 351 &actual_mech_type, 352 &output_token, 353 &ret_flags, 354 &lifetime_rec, 355 &gss_delegated_cred_handle); 356 357 358 if (major_status != GSS_S_COMPLETE) { 359 360 major_status = gss_display_name(&status, 361 src_name, 362 &fullname_buffer, 363 &fullname_type); 364 Data(ap, SPX_REJECT, (void *)"auth failed", -1); 365 auth_finished(ap, AUTH_REJECT); 366 return; 367 } 368 369 major_status = gss_display_name(&status, 370 src_name, 371 &fullname_buffer, 372 &fullname_type); 373 374 375 Data(ap, SPX_ACCEPT, (void *)output_token.value, output_token.length); 376 auth_finished(ap, AUTH_USER); 377 break; 378 379 default: 380 Data(ap, SPX_REJECT, 0, 0); 381 break; 382 } 383 } 384 385 386 void 387 spx_reply(ap, data, cnt) 388 Authenticator *ap; 389 unsigned char *data; 390 int cnt; 391 { 392 Session_Key skey; 393 394 if (cnt-- < 1) 395 return; 396 switch (*data++) { 397 case SPX_REJECT: 398 if (cnt > 0) { 399 printf("[ SPX refuses authentication because %.*s ]\r\n", 400 cnt, data); 401 } else 402 printf("[ SPX refuses authentication ]\r\n"); 403 auth_send_retry(); 404 return; 405 case SPX_ACCEPT: 406 printf("[ SPX accepts you ]\n"); 407 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { 408 /* 409 * Send over the encrypted challenge. 410 */ 411 input_token.value = (char *) data; 412 input_token.length = cnt; 413 414 major_status = gss_init_sec_context(&status, /* minor stat */ 415 GSS_C_NO_CREDENTIAL, /* cred handle */ 416 &actual_ctxhandle, /* ctx handle */ 417 desired_targname, /* target name */ 418 GSS_C_NULL_OID, /* mech type */ 419 req_flags, /* req flags */ 420 0, /* time req */ 421 input_chan_bindings, /* chan binding */ 422 &input_token, /* input token */ 423 &actual_mech_type, /* actual mech */ 424 &output_token, /* output token */ 425 &ret_flags, /* ret flags */ 426 &lifetime_rec); /* time rec */ 427 428 if (major_status != GSS_S_COMPLETE) { 429 gss_display_status(&new_status, 430 status, 431 GSS_C_MECH_CODE, 432 GSS_C_NULL_OID, 433 &msg_ctx, 434 &status_string); 435 printf("[ SPX mutual response fails ... '%s' ]\r\n", 436 status_string.value); 437 auth_send_retry(); 438 return; 439 } 440 } 441 auth_finished(ap, AUTH_USER); 442 return; 443 444 default: 445 return; 446 } 447 } 448 449 int 450 spx_status(ap, name, level) 451 Authenticator *ap; 452 char *name; 453 int level; 454 { 455 456 gss_buffer_desc fullname_buffer, acl_file_buffer; 457 gss_OID fullname_type; 458 char acl_file[160], fullname[160]; 459 int major_status, status = 0; 460 struct passwd *pwd; 461 462 /* 463 * hard code fullname to 464 * "SPX:/C=US/O=Digital/OU=LKG/OU=Sphinx/OU=Users/CN=Kannan Alagappan" 465 * and acl_file to "~kannan/.sphinx" 466 */ 467 468 pwd = getpwnam(UserNameRequested); 469 if (pwd == NULL) { 470 return(AUTH_USER); /* not authenticated */ 471 } 472 473 strcpy(acl_file, pwd->pw_dir); 474 strcat(acl_file, "/.sphinx"); 475 acl_file_buffer.value = acl_file; 476 acl_file_buffer.length = strlen(acl_file); 477 478 major_status = gss_display_name(&status, 479 src_name, 480 &fullname_buffer, 481 &fullname_type); 482 483 if (level < AUTH_USER) 484 return(level); 485 486 major_status = gss__check_acl(&status, &fullname_buffer, 487 &acl_file_buffer); 488 489 if (major_status == GSS_S_COMPLETE) { 490 strcpy(name, UserNameRequested); 491 return(AUTH_VALID); 492 } else { 493 return(AUTH_USER); 494 } 495 496 } 497 498 #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} 499 #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} 500 501 void 502 spx_printsub(data, cnt, buf, buflen) 503 unsigned char *data, *buf; 504 int cnt, buflen; 505 { 506 char lbuf[32]; 507 register int i; 508 509 buf[buflen-1] = '\0'; /* make sure its NULL terminated */ 510 buflen -= 1; 511 512 switch(data[3]) { 513 case SPX_REJECT: /* Rejected (reason might follow) */ 514 strncpy((char *)buf, " REJECT ", buflen); 515 goto common; 516 517 case SPX_ACCEPT: /* Accepted (name might follow) */ 518 strncpy((char *)buf, " ACCEPT ", buflen); 519 common: 520 BUMP(buf, buflen); 521 if (cnt <= 4) 522 break; 523 ADDC(buf, buflen, '"'); 524 for (i = 4; i < cnt; i++) 525 ADDC(buf, buflen, data[i]); 526 ADDC(buf, buflen, '"'); 527 ADDC(buf, buflen, '\0'); 528 break; 529 530 case SPX_AUTH: /* Authentication data follows */ 531 strncpy((char *)buf, " AUTH", buflen); 532 goto common2; 533 534 default: 535 sprintf(lbuf, " %d (unknown)", data[3]); 536 strncpy((char *)buf, lbuf, buflen); 537 common2: 538 BUMP(buf, buflen); 539 for (i = 4; i < cnt; i++) { 540 sprintf(lbuf, " %d", data[i]); 541 strncpy((char *)buf, lbuf, buflen); 542 BUMP(buf, buflen); 543 } 544 break; 545 } 546 } 547 548 #endif 549 550 #ifdef notdef 551 552 prkey(msg, key) 553 char *msg; 554 unsigned char *key; 555 { 556 register int i; 557 printf("%s:", msg); 558 for (i = 0; i < 8; i++) 559 printf(" %3d", key[i]); 560 printf("\r\n"); 561 } 562 #endif 563