comparison svr-auth.c @ 33:f789045062e6

Progressing client support
author Matt Johnston <matt@ucc.asn.au>
date Tue, 27 Jul 2004 16:30:46 +0000
parents 469950e86d0f
children 0ad5fb979f42
comparison
equal deleted inserted replaced
32:8fd0cdbb5b1b 33:f789045062e6
39 static void authclear(); 39 static void authclear();
40 static int checkusername(unsigned char *username, unsigned int userlen); 40 static int checkusername(unsigned char *username, unsigned int userlen);
41 static void send_msg_userauth_banner(); 41 static void send_msg_userauth_banner();
42 42
43 /* initialise the first time for a session, resetting all parameters */ 43 /* initialise the first time for a session, resetting all parameters */
44 void authinitialise() { 44 void svr_authinitialise() {
45 45
46 svr_ses.authstate.failcount = 0; 46 ses.authstate.failcount = 0;
47 authclear(); 47 authclear();
48 48
49 } 49 }
50 50
51 /* Reset the auth state, but don't reset the failcount. This is for if the 51 /* Reset the auth state, but don't reset the failcount. This is for if the
52 * user decides to try with a different username etc, and is also invoked 52 * user decides to try with a different username etc, and is also invoked
53 * on initialisation */ 53 * on initialisation */
54 static void authclear() { 54 static void authclear() {
55 55
56 ses.authdone = 0; 56 memset(&ses.authstate, 0, sizeof(ses.authstate));
57 svr_ses.authstate.pw = NULL;
58 svr_ses.authstate.username = NULL;
59 svr_ses.authstate.printableuser = NULL;
60 svr_ses.authstate.authtypes = 0;
61 #ifdef DROPBEAR_PUBKEY_AUTH 57 #ifdef DROPBEAR_PUBKEY_AUTH
62 svr_ses.authstate.authtypes |= AUTH_TYPE_PUBKEY; 58 ses.authstate.authtypes |= AUTH_TYPE_PUBKEY;
63 #endif 59 #endif
64 #ifdef DROPBEAR_PASSWORD_AUTH 60 #ifdef DROPBEAR_PASSWORD_AUTH
65 if (svr_opts.noauthpass) { 61 if (svr_opts.noauthpass) {
66 svr_ses.authstate.authtypes |= AUTH_TYPE_PASSWORD; 62 ses.authstate.authtypes |= AUTH_TYPE_PASSWORD;
67 } 63 }
68 #endif 64 #endif
69 65
70 } 66 }
71 67
101 unsigned int userlen, servicelen, methodlen; 97 unsigned int userlen, servicelen, methodlen;
102 98
103 TRACE(("enter recv_msg_userauth_request")); 99 TRACE(("enter recv_msg_userauth_request"));
104 100
105 /* ignore packets if auth is already done */ 101 /* ignore packets if auth is already done */
106 if (ses.authdone == 1) { 102 if (ses.authstate.authdone == 1) {
107 return; 103 return;
108 } 104 }
109 105
110 /* send the banner if it exists, it will only exist once */ 106 /* send the banner if it exists, it will only exist once */
111 if (svr_opts.banner) { 107 if (svr_opts.banner) {
145 goto out; 141 goto out;
146 } 142 }
147 143
148 #ifdef DROPBEAR_PASSWORD_AUTH 144 #ifdef DROPBEAR_PASSWORD_AUTH
149 if (!svr_opts.noauthpass && 145 if (!svr_opts.noauthpass &&
150 !(svr_opts.norootpass && svr_ses.authstate.pw->pw_uid == 0) ) { 146 !(svr_opts.norootpass && ses.authstate.pw->pw_uid == 0) ) {
151 /* user wants to try password auth */ 147 /* user wants to try password auth */
152 if (methodlen == AUTH_METHOD_PASSWORD_LEN && 148 if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
153 strncmp(methodname, AUTH_METHOD_PASSWORD, 149 strncmp(methodname, AUTH_METHOD_PASSWORD,
154 AUTH_METHOD_PASSWORD_LEN) == 0) { 150 AUTH_METHOD_PASSWORD_LEN) == 0) {
155 passwordauth(); 151 svr_auth_password();
156 goto out; 152 goto out;
157 } 153 }
158 } 154 }
159 #endif 155 #endif
160 156
161 #ifdef DROPBEAR_PUBKEY_AUTH 157 #ifdef DROPBEAR_PUBKEY_AUTH
162 /* user wants to try pubkey auth */ 158 /* user wants to try pubkey auth */
163 if (methodlen == AUTH_METHOD_PUBKEY_LEN && 159 if (methodlen == AUTH_METHOD_PUBKEY_LEN &&
164 strncmp(methodname, AUTH_METHOD_PUBKEY, 160 strncmp(methodname, AUTH_METHOD_PUBKEY,
165 AUTH_METHOD_PUBKEY_LEN) == 0) { 161 AUTH_METHOD_PUBKEY_LEN) == 0) {
166 pubkeyauth(); 162 svr_auth_pubkey();
167 goto out; 163 goto out;
168 } 164 }
169 #endif 165 #endif
170 166
171 /* nothing matched, we just fail */ 167 /* nothing matched, we just fail */
190 if (userlen > MAX_USERNAME_LEN) { 186 if (userlen > MAX_USERNAME_LEN) {
191 return DROPBEAR_FAILURE; 187 return DROPBEAR_FAILURE;
192 } 188 }
193 189
194 /* new user or username has changed */ 190 /* new user or username has changed */
195 if (svr_ses.authstate.username == NULL || 191 if (ses.authstate.username == NULL ||
196 strcmp(username, svr_ses.authstate.username) != 0) { 192 strcmp(username, ses.authstate.username) != 0) {
197 /* the username needs resetting */ 193 /* the username needs resetting */
198 if (svr_ses.authstate.username != NULL) { 194 if (ses.authstate.username != NULL) {
199 dropbear_log(LOG_WARNING, "client trying multiple usernames"); 195 dropbear_log(LOG_WARNING, "client trying multiple usernames");
200 m_free(svr_ses.authstate.username); 196 m_free(ses.authstate.username);
201 } 197 }
202 authclear(); 198 authclear();
203 svr_ses.authstate.pw = getpwnam((char*)username); 199 ses.authstate.pw = getpwnam((char*)username);
204 svr_ses.authstate.username = m_strdup(username); 200 ses.authstate.username = m_strdup(username);
205 m_free(svr_ses.authstate.printableuser); 201 m_free(ses.authstate.printableuser);
206 } 202 }
207 203
208 /* check that user exists */ 204 /* check that user exists */
209 if (svr_ses.authstate.pw == NULL) { 205 if (ses.authstate.pw == NULL) {
210 TRACE(("leave checkusername: user '%s' doesn't exist", username)); 206 TRACE(("leave checkusername: user '%s' doesn't exist", username));
211 dropbear_log(LOG_WARNING, 207 dropbear_log(LOG_WARNING,
212 "login attempt for nonexistent user"); 208 "login attempt for nonexistent user");
213 send_msg_userauth_failure(0, 1); 209 send_msg_userauth_failure(0, 1);
214 return DROPBEAR_FAILURE; 210 return DROPBEAR_FAILURE;
215 } 211 }
216 212
217 /* We can set it once we know its a real user */ 213 /* We can set it once we know its a real user */
218 svr_ses.authstate.printableuser = m_strdup(svr_ses.authstate.pw->pw_name); 214 ses.authstate.printableuser = m_strdup(ses.authstate.pw->pw_name);
219 215
220 /* check for non-root if desired */ 216 /* check for non-root if desired */
221 if (svr_opts.norootlogin && svr_ses.authstate.pw->pw_uid == 0) { 217 if (svr_opts.norootlogin && ses.authstate.pw->pw_uid == 0) {
222 TRACE(("leave checkusername: root login disabled")); 218 TRACE(("leave checkusername: root login disabled"));
223 dropbear_log(LOG_WARNING, "root login rejected"); 219 dropbear_log(LOG_WARNING, "root login rejected");
224 send_msg_userauth_failure(0, 1); 220 send_msg_userauth_failure(0, 1);
225 return DROPBEAR_FAILURE; 221 return DROPBEAR_FAILURE;
226 } 222 }
227 223
228 /* check for an empty password */ 224 /* check for an empty password */
229 if (svr_ses.authstate.pw->pw_passwd[0] == '\0') { 225 if (ses.authstate.pw->pw_passwd[0] == '\0') {
230 TRACE(("leave checkusername: empty pword")); 226 TRACE(("leave checkusername: empty pword"));
231 dropbear_log(LOG_WARNING, "user '%s' has blank password, rejected", 227 dropbear_log(LOG_WARNING, "user '%s' has blank password, rejected",
232 svr_ses.authstate.printableuser); 228 ses.authstate.printableuser);
233 send_msg_userauth_failure(0, 1); 229 send_msg_userauth_failure(0, 1);
234 return DROPBEAR_FAILURE; 230 return DROPBEAR_FAILURE;
235 } 231 }
236 232
237 TRACE(("shell is %s", svr_ses.authstate.pw->pw_shell)); 233 TRACE(("shell is %s", ses.authstate.pw->pw_shell));
238 234
239 /* check that the shell is set */ 235 /* check that the shell is set */
240 usershell = svr_ses.authstate.pw->pw_shell; 236 usershell = ses.authstate.pw->pw_shell;
241 if (usershell[0] == '\0') { 237 if (usershell[0] == '\0') {
242 /* empty shell in /etc/passwd means /bin/sh according to passwd(5) */ 238 /* empty shell in /etc/passwd means /bin/sh according to passwd(5) */
243 usershell = "/bin/sh"; 239 usershell = "/bin/sh";
244 } 240 }
245 241
256 } 252 }
257 /* no matching shell */ 253 /* no matching shell */
258 endusershell(); 254 endusershell();
259 TRACE(("no matching shell")); 255 TRACE(("no matching shell"));
260 dropbear_log(LOG_WARNING, "user '%s' has invalid shell, rejected", 256 dropbear_log(LOG_WARNING, "user '%s' has invalid shell, rejected",
261 svr_ses.authstate.printableuser); 257 ses.authstate.printableuser);
262 send_msg_userauth_failure(0, 1); 258 send_msg_userauth_failure(0, 1);
263 return DROPBEAR_FAILURE; 259 return DROPBEAR_FAILURE;
264 260
265 goodshell: 261 goodshell:
266 endusershell(); 262 endusershell();
267 TRACE(("matching shell")); 263 TRACE(("matching shell"));
268 264
269 TRACE(("uid = %d", svr_ses.authstate.pw->pw_uid)); 265 TRACE(("uid = %d", ses.authstate.pw->pw_uid));
270 TRACE(("leave checkusername")); 266 TRACE(("leave checkusername"));
271 return DROPBEAR_SUCCESS; 267 return DROPBEAR_SUCCESS;
272 268
273 } 269 }
274 270
288 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_FAILURE); 284 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_FAILURE);
289 285
290 /* put a list of allowed types */ 286 /* put a list of allowed types */
291 typebuf = buf_new(30); /* long enough for PUBKEY and PASSWORD */ 287 typebuf = buf_new(30); /* long enough for PUBKEY and PASSWORD */
292 288
293 if (svr_ses.authstate.authtypes & AUTH_TYPE_PUBKEY) { 289 if (ses.authstate.authtypes & AUTH_TYPE_PUBKEY) {
294 buf_putbytes(typebuf, AUTH_METHOD_PUBKEY, AUTH_METHOD_PUBKEY_LEN); 290 buf_putbytes(typebuf, AUTH_METHOD_PUBKEY, AUTH_METHOD_PUBKEY_LEN);
295 if (svr_ses.authstate.authtypes & AUTH_TYPE_PASSWORD) { 291 if (ses.authstate.authtypes & AUTH_TYPE_PASSWORD) {
296 buf_putbyte(typebuf, ','); 292 buf_putbyte(typebuf, ',');
297 } 293 }
298 } 294 }
299 295
300 if (svr_ses.authstate.authtypes & AUTH_TYPE_PASSWORD) { 296 if (ses.authstate.authtypes & AUTH_TYPE_PASSWORD) {
301 buf_putbytes(typebuf, AUTH_METHOD_PASSWORD, AUTH_METHOD_PASSWORD_LEN); 297 buf_putbytes(typebuf, AUTH_METHOD_PASSWORD, AUTH_METHOD_PASSWORD_LEN);
302 } 298 }
303 299
304 buf_setpos(typebuf, 0); 300 buf_setpos(typebuf, 0);
305 buf_putstring(ses.writepayload, buf_getptr(typebuf, typebuf->len), 301 buf_putstring(ses.writepayload, buf_getptr(typebuf, typebuf->len),
309 buf_putbyte(ses.writepayload, partial ? 1 : 0); 305 buf_putbyte(ses.writepayload, partial ? 1 : 0);
310 encrypt_packet(); 306 encrypt_packet();
311 307
312 if (incrfail) { 308 if (incrfail) {
313 usleep(300000); /* XXX improve this */ 309 usleep(300000); /* XXX improve this */
314 svr_ses.authstate.failcount++; 310 ses.authstate.failcount++;
315 } 311 }
316 312
317 if (svr_ses.authstate.failcount >= MAX_AUTH_TRIES) { 313 if (ses.authstate.failcount >= MAX_AUTH_TRIES) {
318 char * userstr; 314 char * userstr;
319 /* XXX - send disconnect ? */ 315 /* XXX - send disconnect ? */
320 TRACE(("Max auth tries reached, exiting")); 316 TRACE(("Max auth tries reached, exiting"));
321 317
322 if (svr_ses.authstate.printableuser == NULL) { 318 if (ses.authstate.printableuser == NULL) {
323 userstr = "is invalid"; 319 userstr = "is invalid";
324 } else { 320 } else {
325 userstr = svr_ses.authstate.printableuser; 321 userstr = ses.authstate.printableuser;
326 } 322 }
327 dropbear_exit("Max auth tries reached - user %s", userstr); 323 dropbear_exit("Max auth tries reached - user %s", userstr);
328 } 324 }
329 325
330 TRACE(("leave send_msg_userauth_failure")); 326 TRACE(("leave send_msg_userauth_failure"));
338 CHECKCLEARTOWRITE(); 334 CHECKCLEARTOWRITE();
339 335
340 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_SUCCESS); 336 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_SUCCESS);
341 encrypt_packet(); 337 encrypt_packet();
342 338
343 ses.authdone = 1; 339 ses.authstate.authdone = 1;
344 340
345 if (svr_ses.authstate.pw->pw_uid == 0) { 341 if (ses.authstate.pw->pw_uid == 0) {
346 ses.allowprivport = 1; 342 ses.allowprivport = 1;
347 } 343 }
348 344
349 /* Remove from the list of pre-auth sockets. Should be m_close(), since if 345 /* Remove from the list of pre-auth sockets. Should be m_close(), since if
350 * we fail, we might end up leaking connection slots, and disallow new 346 * we fail, we might end up leaking connection slots, and disallow new