~ubuntu-branches/debian/stretch/dropbear/stretch

« back to all changes in this revision

Viewing changes to svr-auth.c

  • Committer: Package Import Robot
  • Author(s): Gerrit Pape, Matt Johnston, Gerrit Pape
  • Date: 2013-10-25 15:00:48 UTC
  • mfrom: (1.4.6)
  • Revision ID: package-import@ubuntu.com-20131025150048-3jq765x96xayk392
Tags: 2013.60-1
[ Matt Johnston ]
* New upstream release.

[ Gerrit Pape ]
* debian/diff/0004-cve-2013-4421.diff, 0005-user-disclosure.diff:
  remove; fixed upstream.
* debian/dropbear.postinst: don't fail if initramfs-tools it not
  installed (closes: #692653).

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
 
38
38
static void authclear();
39
39
static int checkusername(unsigned char *username, unsigned int userlen);
40
 
static void send_msg_userauth_banner();
41
40
 
42
41
/* initialise the first time for a session, resetting all parameters */
43
42
void svr_authinitialise() {
82
81
 
83
82
/* Send a banner message if specified to the client. The client might
84
83
 * ignore this, but possibly serves as a legal "no trespassing" sign */
85
 
static void send_msg_userauth_banner() {
 
84
void send_msg_userauth_banner(buffer *banner) {
86
85
 
87
86
        TRACE(("enter send_msg_userauth_banner"))
88
 
        if (svr_opts.banner == NULL) {
89
 
                TRACE(("leave send_msg_userauth_banner: banner is NULL"))
90
 
                return;
91
 
        }
92
87
 
93
88
        CHECKCLEARTOWRITE();
94
89
 
95
90
        buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_BANNER);
96
 
        buf_putstring(ses.writepayload, buf_getptr(svr_opts.banner,
97
 
                                svr_opts.banner->len), svr_opts.banner->len);
 
91
        buf_putstring(ses.writepayload, buf_getptr(banner, banner->len),
 
92
                        banner->len);
98
93
        buf_putstring(ses.writepayload, "en", 2);
99
94
 
100
95
        encrypt_packet();
101
 
        buf_free(svr_opts.banner);
102
 
        svr_opts.banner = NULL;
103
96
 
104
97
        TRACE(("leave send_msg_userauth_banner"))
105
98
}
110
103
 
111
104
        unsigned char *username = NULL, *servicename = NULL, *methodname = NULL;
112
105
        unsigned int userlen, servicelen, methodlen;
 
106
        int valid_user = 0;
113
107
 
114
108
        TRACE(("enter recv_msg_userauth_request"))
115
109
 
121
115
 
122
116
        /* send the banner if it exists, it will only exist once */
123
117
        if (svr_opts.banner) {
124
 
                send_msg_userauth_banner();
 
118
                send_msg_userauth_banner(svr_opts.banner);
 
119
                buf_free(svr_opts.banner);
 
120
                svr_opts.banner = NULL;
125
121
        }
126
122
 
127
 
        
128
123
        username = buf_getstring(ses.payload, &userlen);
129
124
        servicename = buf_getstring(ses.payload, &servicelen);
130
125
        methodname = buf_getstring(ses.payload, &methodlen);
141
136
                dropbear_exit("unknown service in auth");
142
137
        }
143
138
 
 
139
        /* check username is good before continuing. 
 
140
         * the 'incrfail' varies depending on the auth method to
 
141
         * avoid giving away which users exist on the system through
 
142
         * the time delay. */
 
143
        if (checkusername(username, userlen) == DROPBEAR_SUCCESS) {
 
144
                valid_user = 1;
 
145
        }
 
146
 
144
147
        /* user wants to know what methods are supported */
145
148
        if (methodlen == AUTH_METHOD_NONE_LEN &&
146
149
                        strncmp(methodname, AUTH_METHOD_NONE,
147
150
                                AUTH_METHOD_NONE_LEN) == 0) {
148
151
                TRACE(("recv_msg_userauth_request: 'none' request"))
149
 
                send_msg_userauth_failure(0, 0);
150
 
                goto out;
 
152
                if (valid_user
 
153
                                && svr_opts.allowblankpass
 
154
                                && !svr_opts.noauthpass
 
155
                                && !(svr_opts.norootpass && ses.authstate.pw_uid == 0) 
 
156
                                && ses.authstate.pw_passwd[0] == '\0') 
 
157
                {
 
158
                        dropbear_log(LOG_NOTICE, 
 
159
                                        "Auth succeeded with blank password for '%s' from %s",
 
160
                                        ses.authstate.pw_name,
 
161
                                        svr_ses.addrstring);
 
162
                        send_msg_userauth_success();
 
163
                        goto out;
 
164
                }
 
165
                else
 
166
                {
 
167
                        /* 'none' has no failure delay */
 
168
                        send_msg_userauth_failure(0, 0);
 
169
                        goto out;
 
170
                }
151
171
        }
152
172
        
153
 
        /* check username is good before continuing */
154
 
        if (checkusername(username, userlen) == DROPBEAR_FAILURE) {
155
 
                /* username is invalid/no shell/etc - send failure */
156
 
                TRACE(("sending checkusername failure"))
157
 
                send_msg_userauth_failure(0, 1);
158
 
                goto out;
159
 
        }
160
 
 
161
173
#ifdef ENABLE_SVR_PASSWORD_AUTH
162
174
        if (!svr_opts.noauthpass &&
163
175
                        !(svr_opts.norootpass && ses.authstate.pw_uid == 0) ) {
165
177
                if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
166
178
                                strncmp(methodname, AUTH_METHOD_PASSWORD,
167
179
                                        AUTH_METHOD_PASSWORD_LEN) == 0) {
168
 
                        svr_auth_password();
169
 
                        goto out;
 
180
                        if (valid_user) {
 
181
                                svr_auth_password();
 
182
                                goto out;
 
183
                        }
170
184
                }
171
185
        }
172
186
#endif
178
192
                if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
179
193
                                strncmp(methodname, AUTH_METHOD_PASSWORD,
180
194
                                        AUTH_METHOD_PASSWORD_LEN) == 0) {
181
 
                        svr_auth_pam();
182
 
                        goto out;
 
195
                        if (valid_user) {
 
196
                                svr_auth_pam();
 
197
                                goto out;
 
198
                        }
183
199
                }
184
200
        }
185
201
#endif
189
205
        if (methodlen == AUTH_METHOD_PUBKEY_LEN &&
190
206
                        strncmp(methodname, AUTH_METHOD_PUBKEY,
191
207
                                AUTH_METHOD_PUBKEY_LEN) == 0) {
192
 
                svr_auth_pubkey();
 
208
                if (valid_user) {
 
209
                        svr_auth_pubkey();
 
210
                } else {
 
211
                        /* pubkey has no failure delay */
 
212
                        send_msg_userauth_failure(0, 0);
 
213
                }
193
214
                goto out;
194
215
        }
195
216
#endif
196
217
 
197
 
        /* nothing matched, we just fail */
 
218
        /* nothing matched, we just fail with a delay */
198
219
        send_msg_userauth_failure(0, 1);
199
220
 
200
221
out:
205
226
}
206
227
 
207
228
 
208
 
/* Check that the username exists, has a non-empty password, and has a valid
209
 
 * shell.
 
229
/* Check that the username exists and isn't disallowed (root), and has a valid shell.
210
230
 * returns DROPBEAR_SUCCESS on valid username, DROPBEAR_FAILURE on failure */
211
231
static int checkusername(unsigned char *username, unsigned int userlen) {
212
232
 
213
233
        char* listshell = NULL;
214
234
        char* usershell = NULL;
 
235
        int   uid;
215
236
        TRACE(("enter checkusername"))
216
237
        if (userlen > MAX_USERNAME_LEN) {
217
238
                return DROPBEAR_FAILURE;
237
258
                dropbear_log(LOG_WARNING,
238
259
                                "Login attempt for nonexistent user from %s",
239
260
                                svr_ses.addrstring);
240
 
                send_msg_userauth_failure(0, 1);
 
261
                return DROPBEAR_FAILURE;
 
262
        }
 
263
 
 
264
        /* check if we are running as non-root, and login user is different from the server */
 
265
        uid = geteuid();
 
266
        if (uid != 0 && uid != ses.authstate.pw_uid) {
 
267
                TRACE(("running as nonroot, only server uid is allowed"))
 
268
                dropbear_log(LOG_WARNING,
 
269
                                "Login attempt with wrong user %s from %s",
 
270
                                ses.authstate.pw_name,
 
271
                                svr_ses.addrstring);
241
272
                return DROPBEAR_FAILURE;
242
273
        }
243
274
 
245
276
        if (svr_opts.norootlogin && ses.authstate.pw_uid == 0) {
246
277
                TRACE(("leave checkusername: root login disabled"))
247
278
                dropbear_log(LOG_WARNING, "root login rejected");
248
 
                send_msg_userauth_failure(0, 1);
249
279
                return DROPBEAR_FAILURE;
250
280
        }
251
281
 
274
304
        TRACE(("no matching shell"))
275
305
        dropbear_log(LOG_WARNING, "User '%s' has invalid shell, rejected",
276
306
                                ses.authstate.pw_name);
277
 
        send_msg_userauth_failure(0, 1);
278
307
        return DROPBEAR_FAILURE;
279
308
        
280
309
goodshell:
284
313
        TRACE(("uid = %d", ses.authstate.pw_uid))
285
314
        TRACE(("leave checkusername"))
286
315
        return DROPBEAR_SUCCESS;
287
 
 
288
316
}
289
317
 
290
318
/* Send a failure message to the client, in responds to a userauth_request.
331
359
        if (incrfail) {
332
360
                unsigned int delay;
333
361
                genrandom((unsigned char*)&delay, sizeof(delay));
334
 
                /* We delay for 300ms +- 50ms, 0.1ms granularity */
335
 
                delay = 250000 + (delay % 1000)*100;
 
362
                /* We delay for 300ms +- 50ms */
 
363
                delay = 250000 + (delay % 100000);
336
364
                usleep(delay);
337
365
                ses.authstate.failcount++;
338
366
        }