Stop building multiple versions of telnet.
[dragonfly.git] / lib / libtelnet / krb4encpwd.c
blob0eb969cf73642f590395b67553cc0d9cbcf6d7b5
1 /*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
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.
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.
33 * @(#)krb4encpwd.c 8.3 (Berkeley) 5/30/95
34 * $FreeBSD: src/crypto/telnet/libtelnet/krb4encpwd.c,v 1.3.2.1 2002/04/13 10:59:07 markm Exp $
35 * $DragonFly: src/crypto/telnet/libtelnet/krb4encpwd.c,v 1.2 2003/06/17 04:24:37 dillon Exp $
38 #ifdef KRB4_ENCPWD
40 * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
41 * ALL RIGHTS RESERVED
43 * "Digital Equipment Corporation authorizes the reproduction,
44 * distribution and modification of this software subject to the following
45 * restrictions:
47 * 1. Any partial or whole copy of this software, or any modification
48 * thereof, must include this copyright notice in its entirety.
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.
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.
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.
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"
72 #include <sys/types.h>
73 #include <openssl/des.h>
74 #include <arpa/telnet.h>
75 #include <krb.h>
76 #include <pwd.h>
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <string.h>
81 #include "encrypt.h"
82 #include "auth.h"
83 #include "misc.h"
85 int krb_mk_encpwd_req(KTEXT, char *, char *, char *, char *, char *, char *);
86 int krb_rd_encpwd_req(KTEXT, char *, char *, u_long, AUTH_DAT *, char *, char *, char *, char *);
88 extern auth_debug_mode;
90 static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
91 AUTHTYPE_KRB4_ENCPWD, };
92 static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
93 TELQUAL_NAME, };
95 #define KRB4_ENCPWD_AUTH 0 /* Authentication data follows */
96 #define KRB4_ENCPWD_REJECT 1 /* Rejected (reason might follow) */
97 #define KRB4_ENCPWD_ACCEPT 2 /* Accepted */
98 #define KRB4_ENCPWD_CHALLENGE 3 /* Challenge for mutual auth. */
99 #define KRB4_ENCPWD_ACK 4 /* Acknowledge */
101 #define KRB_SERVICE_NAME "rcmd"
103 static KTEXT_ST auth;
104 static char name[ANAME_SZ];
105 static char user_passwd[ANAME_SZ];
106 static AUTH_DAT adat = { 0 };
107 #ifdef ENCRYPTION
108 static Block session_key = { 0 };
109 #endif /* ENCRYPTION */
110 static char challenge[REALM_SZ];
112 static int
113 Data(ap, type, d, c)
114 Authenticator *ap;
115 int type;
116 void *d;
117 int c;
119 unsigned char *p = str_data + 4;
120 unsigned char *cd = (unsigned char *)d;
122 if (c == -1)
123 c = strlen((char *)cd);
125 if (0) {
126 printf("%s:%d: [%d] (%d)",
127 str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
128 str_data[3],
129 type, c);
130 printd(d, c);
131 printf("\r\n");
133 *p++ = ap->type;
134 *p++ = ap->way;
135 *p++ = type;
136 while (c-- > 0) {
137 if ((*p++ = *cd++) == IAC)
138 *p++ = IAC;
140 *p++ = IAC;
141 *p++ = SE;
142 if (str_data[3] == TELQUAL_IS)
143 printsub('>', &str_data[2], p - (&str_data[2]));
144 return(net_write(str_data, p - str_data));
148 krb4encpwd_init(ap, server)
149 Authenticator *ap;
150 int server;
152 char hostname[80], *cp, *realm;
153 C_Block skey;
155 if (server) {
156 str_data[3] = TELQUAL_REPLY;
157 } else {
158 str_data[3] = TELQUAL_IS;
159 gethostname(hostname, sizeof(hostname));
160 realm = krb_realmofhost(hostname);
161 cp = strchr(hostname, '.');
162 if (*cp != NULL) *cp = NULL;
163 if (read_service_key(KRB_SERVICE_NAME, hostname, realm, 0,
164 KEYFILE, (char *)skey)) {
165 return(0);
168 return(1);
172 krb4encpwd_send(ap)
173 Authenticator *ap;
176 printf("[ Trying KRB4ENCPWD ... ]\n");
177 if (!UserNameRequested) {
178 return(0);
180 if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
181 return(0);
184 if (!Data(ap, KRB4_ENCPWD_ACK, (void *)NULL, 0)) {
185 return(0);
188 return(1);
191 void
192 krb4encpwd_is(ap, data, cnt)
193 Authenticator *ap;
194 unsigned char *data;
195 int cnt;
197 Session_Key skey;
198 Block datablock;
199 char r_passwd[ANAME_SZ], r_user[ANAME_SZ];
200 char lhostname[ANAME_SZ], *cp;
201 int r;
202 time_t now;
204 if (cnt-- < 1)
205 return;
206 switch (*data++) {
207 case KRB4_ENCPWD_AUTH:
208 memmove((void *)auth.dat, (void *)data, auth.length = cnt);
210 gethostname(lhostname, sizeof(lhostname));
211 if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0';
213 if (r = krb_rd_encpwd_req(&auth, KRB_SERVICE_NAME, lhostname, 0, &adat, NULL, challenge, r_user, r_passwd)) {
214 Data(ap, KRB4_ENCPWD_REJECT, (void *)"Auth failed", -1);
215 auth_finished(ap, AUTH_REJECT);
216 return;
218 auth_encrypt_userpwd(r_passwd);
219 if (passwdok(UserNameRequested, UserPassword) == 0) {
221 * illegal username and password
223 Data(ap, KRB4_ENCPWD_REJECT, (void *)"Illegal password", -1);
224 auth_finished(ap, AUTH_REJECT);
225 return;
228 memmove((void *)session_key, (void *)adat.session, sizeof(Block));
229 Data(ap, KRB4_ENCPWD_ACCEPT, (void *)0, 0);
230 auth_finished(ap, AUTH_USER);
231 break;
233 case KRB4_ENCPWD_CHALLENGE:
235 * Take the received random challenge text and save
236 * for future authentication.
238 memmove((void *)challenge, (void *)data, sizeof(Block));
239 break;
242 case KRB4_ENCPWD_ACK:
244 * Receive ack, if mutual then send random challenge
248 * If we are doing mutual authentication, get set up to send
249 * the challenge, and verify it when the response comes back.
252 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
253 register int i;
255 time(&now);
256 sprintf(challenge, "%x", now);
257 Data(ap, KRB4_ENCPWD_CHALLENGE, (void *)challenge, strlen(challenge));
259 break;
261 default:
262 Data(ap, KRB4_ENCPWD_REJECT, 0, 0);
263 break;
268 void
269 krb4encpwd_reply(ap, data, cnt)
270 Authenticator *ap;
271 unsigned char *data;
272 int cnt;
274 Session_Key skey;
275 KTEXT_ST krb_token;
276 Block enckey;
277 CREDENTIALS cred;
278 int r;
279 char randchal[REALM_SZ], instance[ANAME_SZ], *cp;
280 char hostname[80], *realm;
282 if (cnt-- < 1)
283 return;
284 switch (*data++) {
285 case KRB4_ENCPWD_REJECT:
286 if (cnt > 0) {
287 printf("[ KRB4_ENCPWD refuses authentication because %.*s ]\r\n",
288 cnt, data);
289 } else
290 printf("[ KRB4_ENCPWD refuses authentication ]\r\n");
291 auth_send_retry();
292 return;
293 case KRB4_ENCPWD_ACCEPT:
294 printf("[ KRB4_ENCPWD accepts you ]\n");
295 auth_finished(ap, AUTH_USER);
296 return;
297 case KRB4_ENCPWD_CHALLENGE:
299 * Verify that the response to the challenge is correct.
302 gethostname(hostname, sizeof(hostname));
303 realm = krb_realmofhost(hostname);
304 memmove((void *)challenge, (void *)data, cnt);
305 memset(user_passwd, 0, sizeof(user_passwd));
306 local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0);
307 UserPassword = user_passwd;
308 Challenge = challenge;
309 strcpy(instance, RemoteHostName);
310 if ((cp = strchr(instance, '.')) != 0) *cp = '\0';
312 if (r = krb_mk_encpwd_req(&krb_token, KRB_SERVICE_NAME, instance, realm, Challenge, UserNameRequested, user_passwd)) {
313 krb_token.length = 0;
316 if (!Data(ap, KRB4_ENCPWD_AUTH, (void *)krb_token.dat, krb_token.length)) {
317 return;
320 break;
322 default:
323 return;
328 krb4encpwd_status(ap, name, level)
329 Authenticator *ap;
330 char *name;
331 int level;
334 if (level < AUTH_USER)
335 return(level);
337 if (UserNameRequested && passwdok(UserNameRequested, UserPassword)) {
338 strcpy(name, UserNameRequested);
339 return(AUTH_VALID);
340 } else {
341 return(AUTH_USER);
345 #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
346 #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
348 void
349 krb4encpwd_printsub(data, cnt, buf, buflen)
350 unsigned char *data, *buf;
351 int cnt, buflen;
353 char lbuf[32];
354 register int i;
356 buf[buflen-1] = '\0'; /* make sure its NULL terminated */
357 buflen -= 1;
359 switch(data[3]) {
360 case KRB4_ENCPWD_REJECT: /* Rejected (reason might follow) */
361 strncpy((char *)buf, " REJECT ", buflen);
362 goto common;
364 case KRB4_ENCPWD_ACCEPT: /* Accepted (name might follow) */
365 strncpy((char *)buf, " ACCEPT ", buflen);
366 common:
367 BUMP(buf, buflen);
368 if (cnt <= 4)
369 break;
370 ADDC(buf, buflen, '"');
371 for (i = 4; i < cnt; i++)
372 ADDC(buf, buflen, data[i]);
373 ADDC(buf, buflen, '"');
374 ADDC(buf, buflen, '\0');
375 break;
377 case KRB4_ENCPWD_AUTH: /* Authentication data follows */
378 strncpy((char *)buf, " AUTH", buflen);
379 goto common2;
381 case KRB4_ENCPWD_CHALLENGE:
382 strncpy((char *)buf, " CHALLENGE", buflen);
383 goto common2;
385 case KRB4_ENCPWD_ACK:
386 strncpy((char *)buf, " ACK", buflen);
387 goto common2;
389 default:
390 sprintf(lbuf, " %d (unknown)", data[3]);
391 strncpy((char *)buf, lbuf, buflen);
392 common2:
393 BUMP(buf, buflen);
394 for (i = 4; i < cnt; i++) {
395 sprintf(lbuf, " %d", data[i]);
396 strncpy((char *)buf, lbuf, buflen);
397 BUMP(buf, buflen);
399 break;
403 int passwdok(name, passwd)
404 char *name, *passwd;
406 char *crypt();
407 char *salt, *p;
408 struct passwd *pwd;
409 int passwdok_status = 0;
411 if (pwd = getpwnam(name))
412 salt = pwd->pw_passwd;
413 else salt = "xx";
415 p = crypt(passwd, salt);
417 if (pwd && !strcmp(p, pwd->pw_passwd)) {
418 passwdok_status = 1;
419 } else passwdok_status = 0;
420 return(passwdok_status);
423 #endif