Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[games.git] / crypto / kerberosIV / appl / telnet / libtelnet / krb4encpwd.c
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 /* $FreeBSD: src/crypto/kerberosIV/appl/telnet/libtelnet/krb4encpwd.c,v 1.2.2.2 2003/02/13 21:34:35 nectar Exp $ */
34 /* $DragonFly: src/crypto/kerberosIV/appl/telnet/libtelnet/Attic/krb4encpwd.c,v 1.2 2003/06/17 04:24:36 dillon Exp $ */
35
36 #include <config.h>
37
38 RCSID("$Id: krb4encpwd.c,v 1.18 1999/09/16 20:41:34 assar Exp $");
39
40 #ifdef  KRB4_ENCPWD
41 /*
42  * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
43  * ALL RIGHTS RESERVED
44  *
45  * "Digital Equipment Corporation authorizes the reproduction,
46  * distribution and modification of this software subject to the following
47  * restrictions:
48  *
49  * 1.  Any partial or whole copy of this software, or any modification
50  * thereof, must include this copyright notice in its entirety.
51  *
52  * 2.  This software is supplied "as is" with no warranty of any kind,
53  * expressed or implied, for any purpose, including any warranty of fitness
54  * or merchantibility.  DIGITAL assumes no responsibility for the use or
55  * reliability of this software, nor promises to provide any form of
56  * support for it on any basis.
57  *
58  * 3.  Distribution of this software is authorized only if no profit or
59  * remuneration of any kind is received in exchange for such distribution.
60  *
61  * 4.  This software produces public key authentication certificates
62  * bearing an expiration date established by DIGITAL and RSA Data
63  * Security, Inc.  It may cease to generate certificates after the expiration
64  * date.  Any modification of this software that changes or defeats
65  * the expiration date or its effect is unauthorized.
66  *
67  * 5.  Software that will renew or extend the expiration date of
68  * authentication certificates produced by this software may be obtained
69  * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
70  * 94065, (415)595-8782, or from DIGITAL"
71  *
72  */
73
74 #include <sys/types.h>
75 #include <arpa/telnet.h>
76 #include <pwd.h>
77 #include <stdio.h>
78
79 #define OPENSSL_DES_LIBDES_COMPATIBILITY
80 #include <openssl/des.h>
81 #include <krb.h>
82 #include <stdlib.h>
83 #include <string.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 int krb_mk_encpwd_req (KTEXT, char *, char *, char *, char *, char *, char *);
93 int krb_rd_encpwd_req (KTEXT, char *, char *, u_long, AUTH_DAT *, char *, char *, char *, char *);
94
95 extern auth_debug_mode;
96
97 static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
98                                         AUTHTYPE_KRB4_ENCPWD, };
99 static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
100                                         TELQUAL_NAME, };
101
102 #define KRB4_ENCPWD_AUTH        0       /* Authentication data follows */
103 #define KRB4_ENCPWD_REJECT      1       /* Rejected (reason might follow) */
104 #define KRB4_ENCPWD_ACCEPT      2       /* Accepted */
105 #define KRB4_ENCPWD_CHALLENGE   3       /* Challenge for mutual auth. */
106 #define KRB4_ENCPWD_ACK         4       /* Acknowledge */
107
108 #define KRB_SERVICE_NAME    "rcmd"
109
110 static  KTEXT_ST auth;
111 static  char name[ANAME_SZ];
112 static  char user_passwd[ANAME_SZ];
113 static  AUTH_DAT adat = { 0 };
114 static des_key_schedule sched;
115 static char  challenge[REALM_SZ];
116
117         static int
118 Data(ap, type, d, c)
119         Authenticator *ap;
120         int type;
121         void *d;
122         int c;
123 {
124         unsigned char *p = str_data + 4;
125         unsigned char *cd = (unsigned char *)d;
126
127         if (c == -1)
128                 c = strlen(cd);
129
130         if (0) {
131                 printf("%s:%d: [%d] (%d)",
132                         str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
133                         str_data[3],
134                         type, c);
135                 printd(d, c);
136                 printf("\r\n");
137         }
138         *p++ = ap->type;
139         *p++ = ap->way;
140         *p++ = type;
141         while (c-- > 0) {
142                 if ((*p++ = *cd++) == IAC)
143                         *p++ = IAC;
144         }
145         *p++ = IAC;
146         *p++ = SE;
147         if (str_data[3] == TELQUAL_IS)
148                 printsub('>', &str_data[2], p - (&str_data[2]));
149         return(telnet_net_write(str_data, p - str_data));
150 }
151
152         int
153 krb4encpwd_init(ap, server)
154         Authenticator *ap;
155         int server;
156 {
157         char hostname[80], *cp, *realm;
158         des_clock skey;
159
160         if (server) {
161                 str_data[3] = TELQUAL_REPLY;
162         } else {
163                 str_data[3] = TELQUAL_IS;
164                 gethostname(hostname, sizeof(hostname));
165                 realm = krb_realmofhost(hostname);
166                 cp = strchr(hostname, '.');
167                 if (*cp != NULL) *cp = NULL;
168                 if (read_service_key(KRB_SERVICE_NAME, hostname, realm, 0,
169                                         KEYFILE, (char *)skey)) {
170                   return(0);
171                 }
172         }
173         return(1);
174 }
175
176         int
177 krb4encpwd_send(ap)
178         Authenticator *ap;
179 {
180
181         printf("[ Trying KRB4ENCPWD ... ]\r\n");
182         if (!UserNameRequested) {
183                 return(0);
184         }
185         if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
186                 return(0);
187         }
188
189         if (!Data(ap, KRB4_ENCPWD_ACK, NULL, 0)) {
190                 return(0);
191         }
192
193         return(1);
194 }
195
196         void
197 krb4encpwd_is(ap, data, cnt)
198         Authenticator *ap;
199         unsigned char *data;
200         int cnt;
201 {
202         Session_Key skey;
203         des_cblock datablock;
204         char  r_passwd[ANAME_SZ], r_user[ANAME_SZ];
205         char  lhostname[ANAME_SZ], *cp;
206         int r;
207         time_t now;
208
209         if (cnt-- < 1)
210                 return;
211         switch (*data++) {
212         case KRB4_ENCPWD_AUTH:
213                 memmove(auth.dat, data, auth.length = cnt);
214
215                 gethostname(lhostname, sizeof(lhostname));
216                 if ((cp = strchr(lhostname, '.')) != 0)  *cp = '\0';
217
218                 if (r = krb_rd_encpwd_req(&auth, KRB_SERVICE_NAME, lhostname, 0, &adat, NULL, challenge, r_user, r_passwd)) {
219                         Data(ap, KRB4_ENCPWD_REJECT, "Auth failed", -1);
220                         auth_finished(ap, AUTH_REJECT);
221                         return;
222                 }
223                 auth_encrypt_userpwd(r_passwd);
224                 if (passwdok(UserNameRequested, UserPassword) == 0) {
225                   /*
226                    *  illegal username and password
227                    */
228                   Data(ap, KRB4_ENCPWD_REJECT, "Illegal password", -1);
229                   auth_finished(ap, AUTH_REJECT);
230                   return;
231                 }
232
233                 memmove(session_key, adat.session, sizeof(des_cblock));
234                 Data(ap, KRB4_ENCPWD_ACCEPT, 0, 0);
235                 auth_finished(ap, AUTH_USER);
236                 break;
237
238         case KRB4_ENCPWD_CHALLENGE:
239                 /*
240                  *  Take the received random challenge text and save
241                  *  for future authentication.
242                  */
243                 memmove(challenge, data, sizeof(des_cblock));
244                 break;
245
246
247         case KRB4_ENCPWD_ACK:
248                 /*
249                  *  Receive ack, if mutual then send random challenge
250                  */
251
252                 /*
253                  * If we are doing mutual authentication, get set up to send
254                  * the challenge, and verify it when the response comes back.
255                  */
256
257                 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
258                   int i;
259
260                   time(&now);
261                   snprintf(challenge, sizeof(challenge), "%x", now);
262                   Data(ap, KRB4_ENCPWD_CHALLENGE, challenge, strlen(challenge));
263                 }
264                 break;
265
266         default:
267                 Data(ap, KRB4_ENCPWD_REJECT, 0, 0);
268                 break;
269         }
270 }
271
272
273         void
274 krb4encpwd_reply(ap, data, cnt)
275         Authenticator *ap;
276         unsigned char *data;
277         int cnt;
278 {
279         Session_Key skey;
280         KTEXT_ST krb_token;
281         des_cblock enckey;
282         CREDENTIALS cred;
283         int r;
284         char    randchal[REALM_SZ], instance[ANAME_SZ], *cp;
285         char    hostname[80], *realm;
286
287         if (cnt-- < 1)
288                 return;
289         switch (*data++) {
290         case KRB4_ENCPWD_REJECT:
291                 if (cnt > 0) {
292                         printf("[ KRB4_ENCPWD refuses authentication because %.*s ]\r\n",
293                                 cnt, data);
294                 } else
295                         printf("[ KRB4_ENCPWD refuses authentication ]\r\n");
296                 auth_send_retry();
297                 return;
298         case KRB4_ENCPWD_ACCEPT:
299                 printf("[ KRB4_ENCPWD accepts you ]\r\n");
300                 auth_finished(ap, AUTH_USER);
301                 return;
302         case KRB4_ENCPWD_CHALLENGE:
303                 /*
304                  * Verify that the response to the challenge is correct.
305                  */
306
307                 gethostname(hostname, sizeof(hostname));
308                 realm = krb_realmofhost(hostname);
309                 memmove(challenge, data, cnt);
310                 memset(user_passwd, 0, sizeof(user_passwd));
311                 des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0);
312                 UserPassword = user_passwd;
313                 Challenge = challenge;
314                 strlcpy(instance, RemoteHostName, sizeof(instance));
315                 if ((cp = strchr(instance, '.')) != 0)  *cp = '\0';
316
317                 if (r = krb_mk_encpwd_req(&krb_token, KRB_SERVICE_NAME, instance, realm, Challenge, UserNameRequested, user_passwd)) {
318                   krb_token.length = 0;
319                 }
320
321                 if (!Data(ap, KRB4_ENCPWD_AUTH, krb_token.dat, krb_token.length)) {
322                   return;
323                 }
324
325                 break;
326
327         default:
328                 return;
329         }
330 }
331
332         int
333 krb4encpwd_status(ap, name, name_sz, level)
334         Authenticator *ap;
335         char *name;
336         size_t name_sz;
337         int level;
338 {
339
340         if (level < AUTH_USER)
341                 return(level);
342
343         if (UserNameRequested && passwdok(UserNameRequested, UserPassword)) {
344                 strlcpy(name, UserNameRequested, name_sz);
345                 return(AUTH_VALID);
346         } else {
347                 return(AUTH_USER);
348         }
349 }
350
351 #define BUMP(buf, len)          while (*(buf)) {++(buf), --(len);}
352 #define ADDC(buf, len, c)       if ((len) > 0) {*(buf)++ = (c); --(len);}
353
354         void
355 krb4encpwd_printsub(data, cnt, buf, buflen)
356         unsigned char *data, *buf;
357         int cnt, buflen;
358 {
359         int i;
360
361         buf[buflen-1] = '\0';           /* make sure its NULL terminated */
362         buflen -= 1;
363
364         switch(data[3]) {
365         case KRB4_ENCPWD_REJECT:        /* Rejected (reason might follow) */
366                 strlcpy((char *)buf, " REJECT ", buflen);
367                 goto common;
368
369         case KRB4_ENCPWD_ACCEPT:        /* Accepted (name might follow) */
370                 strlcpy((char *)buf, " ACCEPT ", buflen);
371         common:
372                 BUMP(buf, buflen);
373                 if (cnt <= 4)
374                         break;
375                 ADDC(buf, buflen, '"');
376                 for (i = 4; i < cnt; i++)
377                         ADDC(buf, buflen, data[i]);
378                 ADDC(buf, buflen, '"');
379                 ADDC(buf, buflen, '\0');
380                 break;
381
382         case KRB4_ENCPWD_AUTH:          /* Authentication data follows */
383                 strlcpy((char *)buf, " AUTH", buflen);
384                 goto common2;
385
386         case KRB4_ENCPWD_CHALLENGE:
387                 strlcpy((char *)buf, " CHALLENGE", buflen);
388                 goto common2;
389
390         case KRB4_ENCPWD_ACK:
391                 strlcpy((char *)buf, " ACK", buflen);
392                 goto common2;
393
394         default:
395                 snprintf(buf, buflen, " %d (unknown)", data[3]);
396         common2:
397                 BUMP(buf, buflen);
398                 for (i = 4; i < cnt; i++) {
399                         snprintf(buf, buflen, " %d", data[i]);
400                         BUMP(buf, buflen);
401                 }
402                 break;
403         }
404 }
405
406 int passwdok(name, passwd)
407 char *name, *passwd;
408 {
409   char *crypt();
410   char *salt, *p;
411   struct passwd *pwd;
412   int   passwdok_status = 0;
413
414   if (pwd = k_getpwnam(name))
415     salt = pwd->pw_passwd;
416   else salt = "xx";
417
418   p = crypt(passwd, salt);
419
420   if (pwd && !strcmp(p, pwd->pw_passwd)) {
421     passwdok_status = 1;
422   } else passwdok_status = 0;
423   return(passwdok_status);
424 }
425
426 #endif
427
428 #ifdef notdef
429
430 prkey(msg, key)
431         char *msg;
432         unsigned char *key;
433 {
434         int i;
435         printf("%s:", msg);
436         for (i = 0; i < 8; i++)
437                 printf(" %3d", key[i]);
438         printf("\r\n");
439 }
440 #endif