f7f0b3cde60a6b9457d771a304161087f8bb2ba3
[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 #include "tac_plus.h"
21 #include "expire.h"
22
23 static int
24 do_sendpass_fn();
25
26 int sendpass_fn(data)
27 struct authen_data *data;
28 {
29     int status;
30     char *name = data->NAS_id->username;
31     char *port = data->NAS_id->NAS_port;
32
33     if (sendauth_only) {
34         /* sendpass is disallowed */
35         report(LOG_ERR, "%s: %s %s sendpass request rejected",
36                session.peer, session.port, name ? name : "<unknown>");
37         data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
38         return(0);
39     }
40
41     if (STREQ(name, DEFAULT_USERNAME)) {
42         data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
43         status = 0;
44     } else {
45         status = do_sendpass_fn(data);
46     }
47
48     if (debug)
49         report(LOG_INFO, "sendpass query for '%s' %s from %s %s",
50                name && name[0] ? name : "unknown",
51                port && port[0] ? port : "unknown", 
52                session.peer, 
53                (data->status == TAC_PLUS_AUTHEN_STATUS_PASS) ?
54                "accepted" : "rejected");
55
56     return(status);
57 }
58
59 /*
60  * Cleartext password information has been requested.  Look this up in
61  * the config file. Set authen_data->status.
62  *
63  * Any strings pointed to by authen_data must come from the heap. They
64  * will get freed by the caller.
65  *
66  * Return 0 if data->status is valid, otherwise 1 */
67
68 static int
69 do_sendpass_fn(data)
70 struct authen_data *data;
71 {
72     char *name;
73     char *p;
74     int expired;
75     char *exp_date;
76     char *secret;
77
78     data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
79
80     /* We must have a username */
81     if (!data->NAS_id->username[0]) {
82         /* choose_authen should have already asked for a username, so this is
83          * a gross error */
84         data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
85         data->server_msg = tac_strdup("No username supplied");
86         report(LOG_ERR, "%s: No username for sendpass_fn", session.peer);
87         return (0);
88     }
89     name = data->NAS_id->username;
90
91     exp_date = cfg_get_expires(name, TAC_PLUS_RECURSE);
92
93     /* The user exists. Check her expiration date, if any */
94     expired = check_expiration(exp_date);
95
96     switch (expired) {
97     case PW_EXPIRED:
98         data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
99         data->server_msg = tac_strdup("Password has expired");
100         return (0);
101
102     default:
103         data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
104         data->server_msg = tac_strdup("Bad return value for password expiration check");
105         report(LOG_ERR, "%s: Bogus return value %d from check_expiration",
106                session.peer, expired);
107         return (0);
108
109     case PW_OK:
110     case PW_EXPIRING:
111
112         /* The user exists, and has not expired. Return her secret info */
113         switch (data->type) {
114         case TAC_PLUS_AUTHEN_TYPE_CHAP:
115             secret = cfg_get_chap_secret(name, TAC_PLUS_RECURSE);
116             if (!secret)
117                 secret = cfg_get_global_secret(name, TAC_PLUS_RECURSE);
118             break;
119
120 #ifdef MSCHAP
121         case TAC_PLUS_AUTHEN_TYPE_MSCHAP:
122             secret = cfg_get_mschap_secret(name, TAC_PLUS_RECURSE);
123             if (!secret)
124                 secret = cfg_get_global_secret(name, TAC_PLUS_RECURSE);
125             break;
126 #endif /* MSCHAP */
127
128         case TAC_PLUS_AUTHEN_TYPE_ARAP:
129             secret = cfg_get_arap_secret(name, TAC_PLUS_RECURSE);
130             if (!secret)
131                 secret = cfg_get_global_secret(name, TAC_PLUS_RECURSE);
132             break;
133
134         case TAC_PLUS_AUTHEN_TYPE_PAP:
135             secret = cfg_get_opap_secret(name, TAC_PLUS_RECURSE);
136             break;
137
138         default:
139             data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
140             data->server_msg = tac_strdup("Illegal authentication type");
141             report(LOG_ERR, "%s: Illegal authentication type %d",
142                    session.peer, data->type);
143             return (0);
144         }
145
146         if (!secret) {
147             data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
148             data->server_msg = tac_strdup("No secret");
149             return (0);
150         }
151
152         p = tac_find_substring("cleartext ", secret);
153         if (!p) {
154             /* Should never happen */
155             data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
156             data->server_msg = tac_strdup("Illegal secret format");
157             report(LOG_ERR, "%s: Illegal secret format %s",
158                    session.peer, secret);
159             return(0);
160         }
161
162         data->server_data = tac_strdup(p);
163         data->server_dlen = strlen(data->server_data);
164         data->status = TAC_PLUS_AUTHEN_STATUS_PASS;
165         if (expired == PW_EXPIRING) {
166             data->server_msg = tac_strdup("Secret will expire soon");
167         }
168         return (0);
169     }
170     /* never reached */
171 }