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 static int choose_login();
24 static int choose_sendpass();
25 static int choose_sendauth();
30 return(session.version & ~TAC_PLUS_MAJOR_VER_MASK);
34 * Choose an authentication function. Return CHOOSE_OK if chosen,
35 * CHOOSE_GETUSER if we need a username, CHOOSE_FAILED on failure
39 choose_authen(data, type)
40 struct authen_data *data;
41 struct authen_type *type;
43 char *name = data->NAS_id->username;
45 switch (data->action) {
46 case TAC_PLUS_AUTHEN_SENDPASS:
47 return(choose_sendpass(data, type));
49 case TAC_PLUS_AUTHEN_SENDAUTH:
50 return(choose_sendauth(data, type));
52 case TAC_PLUS_AUTHEN_LOGIN:
53 /* For enabling, enable_fn handles everything. Must be minor
56 if (data->service == TAC_PLUS_AUTHEN_SVC_ENABLE) {
57 if (session.version != TAC_PLUS_VER_0) {
58 /* must be version 0 */
61 type->authen_func = enable_fn;
62 strcpy(type->authen_name, "enable_fn");
65 return(choose_login(data, type));
67 case TAC_PLUS_AUTHEN_CHPASS:
68 /* we don't support chpass */
69 return(CHOOSE_FAILED);
75 /* never heard of this lot */
76 report(LOG_ERR, "%s: %s %s Illegal packet ver=%d action=%d type=%d",
79 name ? name : "<unknown>",
84 return(CHOOSE_FAILED);
87 /* Choose an authentication function for action == LOGIN, service != enable */
89 choose_login(data, type)
90 struct authen_data *data;
91 struct authen_type *type;
93 char *name = data->NAS_id->username;
96 switch(type->authen_type) {
97 case TAC_PLUS_AUTHEN_TYPE_ASCII:
98 if (session.version != TAC_PLUS_VER_0) {
103 /* request a user name if not already supplied */
104 return (CHOOSE_GETUSER);
107 /* Does this user require s/key? */
108 cfg_passwd = cfg_get_login_secret(name, TAC_PLUS_RECURSE);
109 if (cfg_passwd && STREQ(cfg_passwd, "skey")) {
110 if (debug & DEBUG_PASSWD_FLAG)
111 report(LOG_DEBUG, "%s %s: user %s requires skey",
112 session.peer, session.port, name);
114 type->authen_func = skey_fn;
115 strcpy(type->authen_name, "skey_fn");
119 "%s %s: user %s s/key support has not been compiled in",
120 name ? name : "<unknown>",
121 session.peer, session.port);
122 return(CHOOSE_FAILED);
126 /* Not an skey user. Must be none, des, cleartext or file password */
127 type->authen_func = default_fn;
128 strcpy(type->authen_name, "default_fn");
131 case TAC_PLUS_AUTHEN_TYPE_ARAP:
134 * If we have no des code we can't do ARAP via SENDAUTH. We'll
135 * have to do it via SENDPASS. Return a down-rev reply
136 * packet and hope the NAS is smart enough to deal with it.
138 session.version = TAC_PLUS_VER_0;
139 report(LOG_ERR, "%s %s: user %s DES is unavailable",
140 name ? name : "<unknown>", session.peer, session.port);
141 return (CHOOSE_FAILED);
142 #endif /* ARAP_DES */
146 case TAC_PLUS_AUTHEN_TYPE_MSCHAP:
149 * If we have no des code we can't do MSCHAP via LOGIN. We'll
150 * have to do it via SENDPASS. Return a down-rev reply
151 * packet and hope the NAS is smart enough to deal with it.
153 session.version = TAC_PLUS_VER_0;
154 report(LOG_ERR, "%s %s: user %s DES is unavailable",
155 name ? name : "<unknown>", session.peer, session.port);
156 return (CHOOSE_FAILED);
157 #endif /* MSCHAP_DES */
161 case TAC_PLUS_AUTHEN_TYPE_PAP:
162 case TAC_PLUS_AUTHEN_TYPE_CHAP:
163 if (session.version == TAC_PLUS_VER_0) {
164 type->authen_func = default_v0_fn;
165 strcpy(type->authen_name, "default_v0_fn");
169 /* Version 1 login/[pap|chap|arap].
170 * The username must in the initial START packet
173 report(LOG_ERR, "%s %s: No user in START packet for PAP/CHAP/ARAP",
174 session.peer, session.port);
175 return (CHOOSE_FAILED);
177 type->authen_func = default_fn;
178 strcpy(type->authen_name, "default_fn");
185 /* Illegal value combination */
186 report(LOG_ERR, "%s: %s %s Illegal packet ver=%d action=%d type=%d",
189 name ? name : "<unknown>",
193 return(CHOOSE_FAILED);
197 choose_sendauth(data, type)
198 struct authen_data *data;
199 struct authen_type *type;
201 char *name = data->NAS_id->username;
203 switch (type->authen_type) {
205 case TAC_PLUS_AUTHEN_TYPE_MSCHAP:
208 * If we have no des code we can't do MSCHAP via SENDAUTH. We'll
209 * have to do it via SENDPASS. Return a down-rev reply
210 * packet and hope the NAS is smart enough to deal with it.
212 session.version = TAC_PLUS_VER_0;
213 report(LOG_ERR, "%s %s: user %s DES is unavailable",
214 name ? name : "<unknown>", session.peer, session.port);
215 return (CHOOSE_FAILED);
216 #endif /* MSCHAP_DES */
220 case TAC_PLUS_AUTHEN_TYPE_CHAP:
221 case TAC_PLUS_AUTHEN_TYPE_PAP:
222 /* Must be minor version 1 */
223 if (session.version != TAC_PLUS_VER_1) {
227 /* The start packet must contain the username */
229 return (CHOOSE_FAILED);
231 type->authen_func = sendauth_fn;
232 strcpy(type->authen_name, "sendauth_fn");
238 /* Illegal value combination */
239 report(LOG_ERR, "%s: %s %s Illegal packet ver=%d action=%d type=%d",
242 name ? name : "<unknown>",
247 return(CHOOSE_FAILED);
250 /* Compatibility routine for (obsolete) minor version == 0 */
252 choose_sendpass(data, type)
253 struct authen_data *data;
254 struct authen_type *type;
256 char *name = data->NAS_id->username;
258 switch (type->authen_type) {
259 case TAC_PLUS_AUTHEN_TYPE_CHAP:
261 case TAC_PLUS_AUTHEN_TYPE_MSCHAP:
263 case TAC_PLUS_AUTHEN_TYPE_PAP:
264 case TAC_PLUS_AUTHEN_TYPE_ARAP:
265 /* must be minor version 0 */
266 if (TAC_PLUS_VER_0 != session.version) {
270 /* We need a username */
272 return (CHOOSE_GETUSER);
275 type->authen_func = sendpass_fn;
276 strcpy(type->authen_name, "sendpass_fn");
283 /* Illegal value combination */
284 report(LOG_ERR, "%s: %s %s Illegal packet ver=%d action=%d type=%d",
287 name ? name : "<unknown>",
292 return(CHOOSE_FAILED);