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.2 (Berkeley) 05/30/95";
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
Data(ap,type,d,c)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
spx_init(ap,server)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
spx_send(ap)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
spx_is(ap,data,cnt)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
spx_reply(ap,data,cnt)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
spx_status(ap,name,level)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
spx_printsub(data,cnt,buf,buflen)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
prkey(msg,key)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