2 Copyright (c) 1995-1998 by Cisco systems, Inc.
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.
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.
23 #include "choose_authen.h"
28 #include "default_fn.h"
29 #include "default_v0_fn.h"
34 #include "do_author.h" /* for "struct identity" */
41 static int choose_sendpass TAC_ARGS((struct authen_data *data, struct authen_type *type));
42 static int choose_sendauth TAC_ARGS((struct authen_data *data, struct authen_type *type));
43 static int choose_login TAC_ARGS((struct authen_data *data, struct authen_type *type));
50 return(session.version & ~TAC_PLUS_MAJOR_VER_MASK);
55 * Choose an authentication function. Return CHOOSE_OK if chosen,
56 * CHOOSE_GETUSER if we need a username, CHOOSE_FAILED on failure
59 int choose_authen TAC_ARGS((struct authen_data *data, struct authen_type *type));
62 choose_authen(data, type)
63 struct authen_data *data;
64 struct authen_type *type;
66 char *name = data->NAS_id->username;
68 switch (data->action) {
69 case TAC_PLUS_AUTHEN_SENDPASS:
70 return(choose_sendpass(data, type));
72 case TAC_PLUS_AUTHEN_SENDAUTH:
73 return(choose_sendauth(data, type));
75 case TAC_PLUS_AUTHEN_LOGIN:
76 /* For enabling, enable_fn handles everything. Must be minor
79 if (data->service == TAC_PLUS_AUTHEN_SVC_ENABLE) {
80 if (session.version != TAC_PLUS_VER_0) {
81 /* must be version 0 */
84 type->authen_func = enable_fn;
85 strcpy(type->authen_name, "enable_fn");
88 return(choose_login(data, type));
90 case TAC_PLUS_AUTHEN_CHPASS:
91 /* we don't support chpass */
92 return(CHOOSE_FAILED);
98 /* never heard of this lot */
99 report(LOG_ERR, "%s: %s %s Illegal packet ver=%d action=%d type=%d",
102 name ? name : "<unknown>",
107 return(CHOOSE_FAILED);
110 static int choose_login TAC_ARGS((struct authen_data *data, struct authen_type *type));
112 /* Choose an authentication function for action == LOGIN, service != enable */
114 choose_login(data, type)
115 struct authen_data *data;
116 struct authen_type *type;
118 const char *name = data->NAS_id->username;
119 const char *cfg_passwd;
121 switch(type->authen_type) {
122 case TAC_PLUS_AUTHEN_TYPE_ASCII:
123 if (session.version != TAC_PLUS_VER_0) {
128 /* request a user name if not already supplied */
129 return (CHOOSE_GETUSER);
132 /* Does this user require s/key? */
133 cfg_passwd = cfg_get_login_secret(name, TAC_PLUS_RECURSE);
134 if (cfg_passwd && STREQ(cfg_passwd, "skey")) {
135 if (debug & DEBUG_PASSWD_FLAG)
136 report(LOG_DEBUG, "%s %s: user %s requires skey",
137 session.peer, session.port, name);
139 type->authen_func = skey_fn;
140 strcpy(type->authen_name, "skey_fn");
144 "%s %s: user %s s/key support has not been compiled in",
145 name ? name : "<unknown>",
146 session.peer, session.port);
147 return(CHOOSE_FAILED);
151 /* Not an skey user. Must be none, des, cleartext or file password */
152 type->authen_func = default_fn;
153 strcpy(type->authen_name, "default_fn");
156 case TAC_PLUS_AUTHEN_TYPE_ARAP:
159 * If we have no des code we can't do ARAP via SENDAUTH. We'll
160 * have to do it via SENDPASS. Return a down-rev reply
161 * packet and hope the NAS is smart enough to deal with it.
163 session.version = TAC_PLUS_VER_0;
164 report(LOG_ERR, "%s %s: user %s DES is unavailable",
165 name ? name : "<unknown>", session.peer, session.port);
166 return (CHOOSE_FAILED);
167 #endif /* ARAP_DES */
171 case TAC_PLUS_AUTHEN_TYPE_MSCHAP:
174 * If we have no des code we can't do MSCHAP via LOGIN. We'll
175 * have to do it via SENDPASS. Return a down-rev reply
176 * packet and hope the NAS is smart enough to deal with it.
178 session.version = TAC_PLUS_VER_0;
179 report(LOG_ERR, "%s %s: user %s DES is unavailable",
180 name ? name : "<unknown>", session.peer, session.port);
181 return (CHOOSE_FAILED);
182 #endif /* MSCHAP_DES */
186 case TAC_PLUS_AUTHEN_TYPE_PAP:
187 case TAC_PLUS_AUTHEN_TYPE_CHAP:
188 if (session.version == TAC_PLUS_VER_0) {
189 type->authen_func = default_v0_fn;
190 strcpy(type->authen_name, "default_v0_fn");
194 /* Version 1 login/[pap|chap|arap].
195 * The username must in the initial START packet
198 report(LOG_ERR, "%s %s: No user in START packet for PAP/CHAP/ARAP",
199 session.peer, session.port);
200 return (CHOOSE_FAILED);
202 type->authen_func = default_fn;
203 strcpy(type->authen_name, "default_fn");
210 /* Illegal value combination */
211 report(LOG_ERR, "%s: %s %s Illegal packet ver=%d action=%d type=%d",
214 name ? name : "<unknown>",
218 return(CHOOSE_FAILED);
221 static int choose_sendauth TAC_ARGS((struct authen_data *data, struct authen_type *type));
224 choose_sendauth(data, type)
225 struct authen_data *data;
226 struct authen_type *type;
228 char *name = data->NAS_id->username;
230 switch (type->authen_type) {
232 case TAC_PLUS_AUTHEN_TYPE_MSCHAP:
235 * If we have no des code we can't do MSCHAP via SENDAUTH. We'll
236 * have to do it via SENDPASS. Return a down-rev reply
237 * packet and hope the NAS is smart enough to deal with it.
239 session.version = TAC_PLUS_VER_0;
240 report(LOG_ERR, "%s %s: user %s DES is unavailable",
241 name ? name : "<unknown>", session.peer, session.port);
242 return (CHOOSE_FAILED);
243 #endif /* MSCHAP_DES */
247 case TAC_PLUS_AUTHEN_TYPE_CHAP:
248 case TAC_PLUS_AUTHEN_TYPE_PAP:
249 /* Must be minor version 1 */
250 if (session.version != TAC_PLUS_VER_1) {
254 /* The start packet must contain the username */
256 return (CHOOSE_FAILED);
258 type->authen_func = sendauth_fn;
259 strcpy(type->authen_name, "sendauth_fn");
265 /* Illegal value combination */
266 report(LOG_ERR, "%s: %s %s Illegal packet ver=%d action=%d type=%d",
269 name ? name : "<unknown>",
274 return(CHOOSE_FAILED);
277 static int choose_sendpass TAC_ARGS((struct authen_data *data, struct authen_type *type));
279 /* Compatibility routine for (obsolete) minor version == 0 */
281 choose_sendpass(data, type)
282 struct authen_data *data;
283 struct authen_type *type;
285 char *name = data->NAS_id->username;
287 switch (type->authen_type) {
288 case TAC_PLUS_AUTHEN_TYPE_CHAP:
290 case TAC_PLUS_AUTHEN_TYPE_MSCHAP:
292 case TAC_PLUS_AUTHEN_TYPE_PAP:
293 case TAC_PLUS_AUTHEN_TYPE_ARAP:
294 /* must be minor version 0 */
295 if (TAC_PLUS_VER_0 != session.version) {
299 /* We need a username */
301 return (CHOOSE_GETUSER);
304 type->authen_func = sendpass_fn;
305 strcpy(type->authen_name, "sendpass_fn");
312 /* Illegal value combination */
313 report(LOG_ERR, "%s: %s %s Illegal packet ver=%d action=%d type=%d",
316 name ? name : "<unknown>",
321 return(CHOOSE_FAILED);