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: spx.c,v 1.17 1999/09/16 20:41:34 assar Exp $"); 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", output_name_buffer.value); fflush(stdout); 241 242 major_status = gss_release_buffer(&status, &output_name_buffer); 243 244 input_chan_bindings = (gss_channel_bindings) 245 malloc(sizeof(gss_channel_bindings_desc)); 246 247 input_chan_bindings->initiator_addrtype = GSS_C_AF_INET; 248 input_chan_bindings->initiator_address.length = 4; 249 address = (char *) malloc(4); 250 input_chan_bindings->initiator_address.value = (char *) address; 251 address[0] = ((from_addr & 0xff000000) >> 24); 252 address[1] = ((from_addr & 0xff0000) >> 16); 253 address[2] = ((from_addr & 0xff00) >> 8); 254 address[3] = (from_addr & 0xff); 255 input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET; 256 input_chan_bindings->acceptor_address.length = 4; 257 address = (char *) malloc(4); 258 input_chan_bindings->acceptor_address.value = (char *) address; 259 address[0] = ((to_addr & 0xff000000) >> 24); 260 address[1] = ((to_addr & 0xff0000) >> 16); 261 address[2] = ((to_addr & 0xff00) >> 8); 262 address[3] = (to_addr & 0xff); 263 input_chan_bindings->application_data.length = 0; 264 265 req_flags = 0; 266 if (deleg_flag) req_flags = req_flags | 1; 267 if (mutual_flag) req_flags = req_flags | 2; 268 if (replay_flag) req_flags = req_flags | 4; 269 if (seq_flag) req_flags = req_flags | 8; 270 271 major_status = gss_init_sec_context(&status, /* minor status */ 272 GSS_C_NO_CREDENTIAL, /* cred handle */ 273 &actual_ctxhandle, /* ctx handle */ 274 desired_targname, /* target name */ 275 GSS_C_NULL_OID, /* mech type */ 276 req_flags, /* req flags */ 277 0, /* time req */ 278 input_chan_bindings, /* chan binding */ 279 GSS_C_NO_BUFFER, /* input token */ 280 &actual_mech_type, /* actual mech */ 281 &output_token, /* output token */ 282 &ret_flags, /* ret flags */ 283 &lifetime_rec); /* time rec */ 284 285 if ((major_status != GSS_S_COMPLETE) && 286 (major_status != GSS_S_CONTINUE_NEEDED)) { 287 gss_display_status(&new_status, 288 status, 289 GSS_C_MECH_CODE, 290 GSS_C_NULL_OID, 291 &msg_ctx, 292 &status_string); 293 printf("%s\n", status_string.value); 294 return(0); 295 } 296 297 if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { 298 return(0); 299 } 300 301 if (!Data(ap, SPX_AUTH, output_token.value, output_token.length)) { 302 return(0); 303 } 304 305 return(1); 306 } 307 308 void 309 spx_is(ap, data, cnt) 310 Authenticator *ap; 311 unsigned char *data; 312 int cnt; 313 { 314 Session_Key skey; 315 des_cblock datablock; 316 int r; 317 318 if (cnt-- < 1) 319 return; 320 switch (*data++) { 321 case SPX_AUTH: 322 input_token.length = cnt; 323 input_token.value = (char *) data; 324 325 gethostname(lhostname, sizeof(lhostname)); 326 327 snprintf(targ_printable, sizeof(targ_printable), 328 "SERVICE:rcmd@%s", lhostname); 329 330 input_name_buffer.length = strlen(targ_printable); 331 input_name_buffer.value = targ_printable; 332 333 major_status = gss_import_name(&status, 334 &input_name_buffer, 335 GSS_C_NULL_OID, 336 &desired_targname); 337 338 major_status = gss_acquire_cred(&status, 339 desired_targname, 340 0, 341 GSS_C_NULL_OID_SET, 342 GSS_C_ACCEPT, 343 &gss_cred_handle, 344 &actual_mechs, 345 &lifetime_rec); 346 347 major_status = gss_release_name(&status, desired_targname); 348 349 input_chan_bindings = (gss_channel_bindings) 350 malloc(sizeof(gss_channel_bindings_desc)); 351 352 input_chan_bindings->initiator_addrtype = GSS_C_AF_INET; 353 input_chan_bindings->initiator_address.length = 4; 354 address = (char *) malloc(4); 355 input_chan_bindings->initiator_address.value = (char *) address; 356 address[0] = ((from_addr & 0xff000000) >> 24); 357 address[1] = ((from_addr & 0xff0000) >> 16); 358 address[2] = ((from_addr & 0xff00) >> 8); 359 address[3] = (from_addr & 0xff); 360 input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET; 361 input_chan_bindings->acceptor_address.length = 4; 362 address = (char *) malloc(4); 363 input_chan_bindings->acceptor_address.value = (char *) address; 364 address[0] = ((to_addr & 0xff000000) >> 24); 365 address[1] = ((to_addr & 0xff0000) >> 16); 366 address[2] = ((to_addr & 0xff00) >> 8); 367 address[3] = (to_addr & 0xff); 368 input_chan_bindings->application_data.length = 0; 369 370 major_status = gss_accept_sec_context(&status, 371 &context_handle, 372 gss_cred_handle, 373 &input_token, 374 input_chan_bindings, 375 &src_name, 376 &actual_mech_type, 377 &output_token, 378 &ret_flags, 379 &lifetime_rec, 380 &gss_delegated_cred_handle); 381 382 383 if (major_status != GSS_S_COMPLETE) { 384 385 major_status = gss_display_name(&status, 386 src_name, 387 &fullname_buffer, 388 &fullname_type); 389 Data(ap, SPX_REJECT, "auth failed", -1); 390 auth_finished(ap, AUTH_REJECT); 391 return; 392 } 393 394 major_status = gss_display_name(&status, 395 src_name, 396 &fullname_buffer, 397 &fullname_type); 398 399 400 Data(ap, SPX_ACCEPT, output_token.value, output_token.length); 401 auth_finished(ap, AUTH_USER); 402 break; 403 404 default: 405 Data(ap, SPX_REJECT, 0, 0); 406 break; 407 } 408 } 409 410 411 void 412 spx_reply(ap, data, cnt) 413 Authenticator *ap; 414 unsigned char *data; 415 int cnt; 416 { 417 Session_Key skey; 418 419 if (cnt-- < 1) 420 return; 421 switch (*data++) { 422 case SPX_REJECT: 423 if (cnt > 0) { 424 printf("[ SPX refuses authentication because %.*s ]\r\n", 425 cnt, data); 426 } else 427 printf("[ SPX refuses authentication ]\r\n"); 428 auth_send_retry(); 429 return; 430 case SPX_ACCEPT: 431 printf("[ SPX accepts you ]\r\n"); 432 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { 433 /* 434 * Send over the encrypted challenge. 435 */ 436 input_token.value = (char *) data; 437 input_token.length = cnt; 438 439 major_status = gss_init_sec_context(&status, /* minor stat */ 440 GSS_C_NO_CREDENTIAL, /* cred handle */ 441 &actual_ctxhandle, /* ctx handle */ 442 desired_targname, /* target name */ 443 GSS_C_NULL_OID, /* mech type */ 444 req_flags, /* req flags */ 445 0, /* time req */ 446 input_chan_bindings, /* chan binding */ 447 &input_token, /* input token */ 448 &actual_mech_type, /* actual mech */ 449 &output_token, /* output token */ 450 &ret_flags, /* ret flags */ 451 &lifetime_rec); /* time rec */ 452 453 if (major_status != GSS_S_COMPLETE) { 454 gss_display_status(&new_status, 455 status, 456 GSS_C_MECH_CODE, 457 GSS_C_NULL_OID, 458 &msg_ctx, 459 &status_string); 460 printf("[ SPX mutual response fails ... '%s' ]\r\n", 461 status_string.value); 462 auth_send_retry(); 463 return; 464 } 465 } 466 auth_finished(ap, AUTH_USER); 467 return; 468 469 default: 470 return; 471 } 472 } 473 474 int 475 spx_status(ap, name, name_sz, level) 476 Authenticator *ap; 477 char *name; 478 size_t name_sz; 479 int level; 480 { 481 482 gss_buffer_desc fullname_buffer, acl_file_buffer; 483 gss_OID fullname_type; 484 char acl_file[160], fullname[160]; 485 int major_status, status = 0; 486 struct passwd *pwd; 487 488 /* 489 * hard code fullname to 490 * "SPX:/C=US/O=Digital/OU=LKG/OU=Sphinx/OU=Users/CN=Kannan Alagappan" 491 * and acl_file to "~kannan/.sphinx" 492 */ 493 494 pwd = k_getpwnam(UserNameRequested); 495 if (pwd == NULL) { 496 return(AUTH_USER); /* not authenticated */ 497 } 498 499 snprintf (acl_file, sizeof(acl_file), 500 "%s/.sphinx", pwd->pw_dir); 501 502 acl_file_buffer.value = acl_file; 503 acl_file_buffer.length = strlen(acl_file); 504 505 major_status = gss_display_name(&status, 506 src_name, 507 &fullname_buffer, 508 &fullname_type); 509 510 if (level < AUTH_USER) 511 return(level); 512 513 major_status = gss__check_acl(&status, &fullname_buffer, 514 &acl_file_buffer); 515 516 if (major_status == GSS_S_COMPLETE) { 517 strlcpy(name, UserNameRequested, name_sz); 518 return(AUTH_VALID); 519 } else { 520 return(AUTH_USER); 521 } 522 523 } 524 525 #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} 526 #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} 527 528 void 529 spx_printsub(data, cnt, buf, buflen) 530 unsigned char *data, *buf; 531 int cnt, buflen; 532 { 533 int i; 534 535 buf[buflen-1] = '\0'; /* make sure its NULL terminated */ 536 buflen -= 1; 537 538 switch(data[3]) { 539 case SPX_REJECT: /* Rejected (reason might follow) */ 540 strlcpy((char *)buf, " REJECT ", buflen); 541 goto common; 542 543 case SPX_ACCEPT: /* Accepted (name might follow) */ 544 strlcpy((char *)buf, " ACCEPT ", buflen); 545 common: 546 BUMP(buf, buflen); 547 if (cnt <= 4) 548 break; 549 ADDC(buf, buflen, '"'); 550 for (i = 4; i < cnt; i++) 551 ADDC(buf, buflen, data[i]); 552 ADDC(buf, buflen, '"'); 553 ADDC(buf, buflen, '\0'); 554 break; 555 556 case SPX_AUTH: /* Authentication data follows */ 557 strlcpy((char *)buf, " AUTH", buflen); 558 goto common2; 559 560 default: 561 snprintf(buf, buflen, " %d (unknown)", data[3]); 562 common2: 563 BUMP(buf, buflen); 564 for (i = 4; i < cnt; i++) { 565 snprintf(buf, buflen, " %d", data[i]); 566 BUMP(buf, buflen); 567 } 568 break; 569 } 570 } 571 572 #endif 573 574 #ifdef notdef 575 576 prkey(msg, key) 577 char *msg; 578 unsigned char *key; 579 { 580 int i; 581 printf("%s:", msg); 582 for (i = 0; i < 8; i++) 583 printf(" %3d", key[i]); 584 printf("\r\n"); 585 } 586 #endif 587