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