comparison svr-authpam.c @ 1617:1fbe598a14fb

Merge bugfix delay invalid users
author Matt Johnston <matt@ucc.asn.au>
date Thu, 23 Aug 2018 23:43:45 +0800
parents 5d2d1021ca00
children 258b57b208ae
comparison
equal deleted inserted replaced
1611:0196f4f83fee 1617:1fbe598a14fb
176 * fairly standard (ie just "what's your username, what's your password, OK"). 176 * fairly standard (ie just "what's your username, what's your password, OK").
177 * 177 *
178 * Keyboard interactive would be a lot nicer, but since PAM is synchronous, it 178 * Keyboard interactive would be a lot nicer, but since PAM is synchronous, it
179 * gets very messy trying to send the interactive challenges, and read the 179 * gets very messy trying to send the interactive challenges, and read the
180 * interactive responses, over the network. */ 180 * interactive responses, over the network. */
181 void svr_auth_pam() { 181 void svr_auth_pam(int valid_user) {
182 182
183 struct UserDataS userData = {NULL, NULL}; 183 struct UserDataS userData = {NULL, NULL};
184 struct pam_conv pamConv = { 184 struct pam_conv pamConv = {
185 pamConvFunc, 185 pamConvFunc,
186 &userData /* submitted to pamvConvFunc as appdata_ptr */ 186 &userData /* submitted to pamvConvFunc as appdata_ptr */
187 }; 187 };
188 const char* printable_user = NULL;
188 189
189 pam_handle_t* pamHandlep = NULL; 190 pam_handle_t* pamHandlep = NULL;
190 191
191 char * password = NULL; 192 char * password = NULL;
192 unsigned int passwordlen; 193 unsigned int passwordlen;
202 goto cleanup; 203 goto cleanup;
203 } 204 }
204 205
205 password = buf_getstring(ses.payload, &passwordlen); 206 password = buf_getstring(ses.payload, &passwordlen);
206 207
208 /* We run the PAM conversation regardless of whether the username is valid
209 in case the conversation function has an inherent delay.
210 Use ses.authstate.username rather than ses.authstate.pw_name.
211 After PAM succeeds we then check the valid_user flag too */
212
207 /* used to pass data to the PAM conversation function - don't bother with 213 /* used to pass data to the PAM conversation function - don't bother with
208 * strdup() etc since these are touched only by our own conversation 214 * strdup() etc since these are touched only by our own conversation
209 * function (above) which takes care of it */ 215 * function (above) which takes care of it */
210 userData.user = ses.authstate.pw_name; 216 userData.user = ses.authstate.username;
211 userData.passwd = password; 217 userData.passwd = password;
218
219 if (ses.authstate.pw_name) {
220 printable_user = ses.authstate.pw_name;
221 } else {
222 printable_user = "<invalid username>";
223 }
212 224
213 /* Init pam */ 225 /* Init pam */
214 if ((rc = pam_start("sshd", NULL, &pamConv, &pamHandlep)) != PAM_SUCCESS) { 226 if ((rc = pam_start("sshd", NULL, &pamConv, &pamHandlep)) != PAM_SUCCESS) {
215 dropbear_log(LOG_WARNING, "pam_start() failed, rc=%d, %s", 227 dropbear_log(LOG_WARNING, "pam_start() failed, rc=%d, %s",
216 rc, pam_strerror(pamHandlep, rc)); 228 rc, pam_strerror(pamHandlep, rc));
240 if ((rc = pam_authenticate(pamHandlep, 0)) != PAM_SUCCESS) { 252 if ((rc = pam_authenticate(pamHandlep, 0)) != PAM_SUCCESS) {
241 dropbear_log(LOG_WARNING, "pam_authenticate() failed, rc=%d, %s", 253 dropbear_log(LOG_WARNING, "pam_authenticate() failed, rc=%d, %s",
242 rc, pam_strerror(pamHandlep, rc)); 254 rc, pam_strerror(pamHandlep, rc));
243 dropbear_log(LOG_WARNING, 255 dropbear_log(LOG_WARNING,
244 "Bad PAM password attempt for '%s' from %s", 256 "Bad PAM password attempt for '%s' from %s",
245 ses.authstate.pw_name, 257 printable_user,
246 svr_ses.addrstring); 258 svr_ses.addrstring);
247 send_msg_userauth_failure(0, 1); 259 send_msg_userauth_failure(0, 1);
248 goto cleanup; 260 goto cleanup;
249 } 261 }
250 262
251 if ((rc = pam_acct_mgmt(pamHandlep, 0)) != PAM_SUCCESS) { 263 if ((rc = pam_acct_mgmt(pamHandlep, 0)) != PAM_SUCCESS) {
252 dropbear_log(LOG_WARNING, "pam_acct_mgmt() failed, rc=%d, %s", 264 dropbear_log(LOG_WARNING, "pam_acct_mgmt() failed, rc=%d, %s",
253 rc, pam_strerror(pamHandlep, rc)); 265 rc, pam_strerror(pamHandlep, rc));
254 dropbear_log(LOG_WARNING, 266 dropbear_log(LOG_WARNING,
255 "Bad PAM password attempt for '%s' from %s", 267 "Bad PAM password attempt for '%s' from %s",
256 ses.authstate.pw_name, 268 printable_user,
257 svr_ses.addrstring); 269 svr_ses.addrstring);
258 send_msg_userauth_failure(0, 1); 270 send_msg_userauth_failure(0, 1);
259 goto cleanup; 271 goto cleanup;
272 }
273
274 if (!valid_user) {
275 /* PAM auth succeeded but the username isn't allowed in for another reason
276 (checkusername() failed) */
277 send_msg_userauth_failure(0, 1);
260 } 278 }
261 279
262 /* successful authentication */ 280 /* successful authentication */
263 dropbear_log(LOG_NOTICE, "PAM password auth succeeded for '%s' from %s", 281 dropbear_log(LOG_NOTICE, "PAM password auth succeeded for '%s' from %s",
264 ses.authstate.pw_name, 282 ses.authstate.pw_name,