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
Data(ap,type,d,c)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
spx_init(ap,server)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
spx_send(ap)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
spx_is(ap,data,cnt)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
spx_reply(ap,data,cnt)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
spx_status(ap,name,name_sz,level)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
spx_printsub(unsigned char * data,size_t cnt,unsigned char * buf,size_t buflen)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
prkey(msg,key)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