Release bumped to "gts4".
[tac_plus.git] / sendpass.c
1 /*
2    Copyright (c) 1995-1998 by Cisco systems, Inc.
3
4    Permission to use, copy, modify, and distribute this software for
5    any purpose and without fee is hereby granted, provided that this
6    copyright and permission notice appear on all copies of the
7    software and supporting documentation, the name of Cisco Systems,
8    Inc. not be used in advertising or publicity pertaining to
9    distribution of the program without specific prior permission, and
10    notice be given in supporting documentation that modification,
11    copying and distribution is by permission of Cisco Systems, Inc.
12
13    Cisco Systems, Inc. makes no representations about the suitability
14    of this software for any purpose.  THIS SOFTWARE IS PROVIDED ``AS
15    IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
16    WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17    FITNESS FOR A PARTICULAR PURPOSE.
18 */
19
20
21 #include "tac_plus.h"
22
23 #include "sendpass.h"
24 #include "expire.h"
25 #include "report.h"
26 #include "utils.h"
27 #include "cfgfile.h"
28 #include "choose_authen.h"              /* for "struct authen_data" */
29 #include "do_author.h"                  /* for "struct identity" */
30 #include "main.h"
31 #include "packet.h"
32
33
34 static int do_sendpass_fn TAC_ARGS((struct authen_data *data));
35
36
37 int sendpass_fn TAC_ARGS((struct authen_data *data));
38
39 int sendpass_fn(data)
40 struct authen_data *data;
41 {
42     int status;
43     char *name = data->NAS_id->username;
44     char *port = data->NAS_id->NAS_port;
45
46     if (sendauth_only) {
47         /* sendpass is disallowed */
48         report(LOG_ERR, "%s: %s %s sendpass request rejected",
49                session.peer, session.port, name ? name : "<unknown>");
50         data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
51         return(0);
52     }
53
54     if (STREQ(name, DEFAULT_USERNAME)) {
55         data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
56         status = 0;
57     } else {
58         status = do_sendpass_fn(data);
59     }
60
61     if (debug)
62         report(LOG_INFO, "sendpass query for '%s' %s from %s %s",
63                name && name[0] ? name : "unknown",
64                port && port[0] ? port : "unknown",
65                session.peer,
66                (data->status == TAC_PLUS_AUTHEN_STATUS_PASS) ?
67                "accepted" : "rejected");
68
69     return(status);
70 }
71
72 /*
73  * Cleartext password information has been requested.  Look this up in
74  * the config file. Set authen_data->status.
75  *
76  * Any strings pointed to by authen_data must come from the heap. They
77  * will get freed by the caller.
78  *
79  * Return 0 if data->status is valid, otherwise 1
80  */
81
82 static int do_sendpass_fn TAC_ARGS((struct authen_data *data));
83
84 static int
85 do_sendpass_fn(data)
86 struct authen_data *data;
87 {
88     const char *name, *exp_date, *secret, *p;
89     int expired;
90
91     data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
92
93     /* We must have a username */
94     if (!data->NAS_id->username[0]) {
95         /* choose_authen should have already asked for a username, so this is
96          * a gross error */
97         data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
98         data->server_msg = tac_strdup("No username supplied");
99         report(LOG_ERR, "%s: No username for sendpass_fn", session.peer);
100         return (0);
101     }
102     name = data->NAS_id->username;
103
104     exp_date = cfg_get_expires(name, TAC_PLUS_RECURSE);
105
106     /* The user exists. Check her expiration date, if any */
107     expired = check_expiration(exp_date);
108
109     switch (expired) {
110     case PW_EXPIRED:
111         data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
112         data->server_msg = tac_strdup("Password has expired");
113         return (0);
114
115     default:
116         data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
117         data->server_msg = tac_strdup("Bad return value for password expiration check");
118         report(LOG_ERR, "%s: Bogus return value %d from check_expiration",
119                session.peer, expired);
120         return (0);
121
122     case PW_OK:
123     case PW_EXPIRING:
124
125         /* The user exists, and has not expired. Return her secret info */
126         switch (data->type) {
127         case TAC_PLUS_AUTHEN_TYPE_CHAP:
128             secret = cfg_get_chap_secret(name, TAC_PLUS_RECURSE);
129             if (!secret)
130                 secret = cfg_get_global_secret(name, TAC_PLUS_RECURSE);
131             break;
132
133 #ifdef MSCHAP
134         case TAC_PLUS_AUTHEN_TYPE_MSCHAP:
135             secret = cfg_get_mschap_secret(name, TAC_PLUS_RECURSE);
136             if (!secret)
137                 secret = cfg_get_global_secret(name, TAC_PLUS_RECURSE);
138             break;
139 #endif /* MSCHAP */
140
141         case TAC_PLUS_AUTHEN_TYPE_ARAP:
142             secret = cfg_get_arap_secret(name, TAC_PLUS_RECURSE);
143             if (!secret)
144                 secret = cfg_get_global_secret(name, TAC_PLUS_RECURSE);
145             break;
146
147         case TAC_PLUS_AUTHEN_TYPE_PAP:
148             secret = cfg_get_opap_secret(name, TAC_PLUS_RECURSE);
149             break;
150
151         default:
152             data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
153             data->server_msg = tac_strdup("Illegal authentication type");
154             report(LOG_ERR, "%s: Illegal authentication type %d",
155                    session.peer, data->type);
156             return (0);
157         }
158
159         if (!secret) {
160             data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
161             data->server_msg = tac_strdup("No secret");
162             return (0);
163         }
164
165         p = tac_find_substring("cleartext ", secret);
166         if (!p) {
167             /* Should never happen */
168             data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
169             data->server_msg = tac_strdup("Illegal secret format");
170             report(LOG_ERR, "%s: Illegal secret format %s",
171                    session.peer, secret);
172             return(0);
173         }
174
175         data->server_data = (unsigned char *) tac_strdup(p);
176         data->server_dlen = strlen((char *) data->server_data);
177         data->status = TAC_PLUS_AUTHEN_STATUS_PASS;
178         if (expired == PW_EXPIRING) {
179             data->server_msg = tac_strdup("Secret will expire soon");
180         }
181         return (0);
182     }
183     /* never reached */
184 }