119 + && strncmp(svc, pam_service, strlen(svc)) == 0) { |
119 + && strncmp(svc, pam_service, strlen(svc)) == 0) { |
120 + free(svc); |
120 + free(svc); |
121 + return (0); |
121 + return (0); |
122 + } |
122 + } |
123 + |
123 + |
|
124 + /* |
|
125 + * Clean up previous PAM state. No need to clean up session |
|
126 + * and creds. |
|
127 + */ |
|
128 + sshpam_authenticated = 0; |
|
129 + sshpam_account_status = -1; |
|
130 + |
|
131 + sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, NULL); |
|
132 + if (sshpam_err != PAM_SUCCESS) |
|
133 + debug3("Cannot remove PAM conv"); /* a warning only */ |
124 +#else /* Original */ |
134 +#else /* Original */ |
125 /* We already have a PAM context; check if the user matches */ |
135 /* We already have a PAM context; check if the user matches */ |
126 sshpam_err = pam_get_item(sshpam_handle, |
136 sshpam_err = pam_get_item(sshpam_handle, |
127 PAM_USER, (sshpam_const void **)ptr_pam_user); |
137 PAM_USER, (sshpam_const void **)ptr_pam_user); |
128 if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0) |
138 if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0) |
144 pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle); |
154 pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle); |
145 +#endif |
155 +#endif |
146 sshpam_authctxt = authctxt; |
156 sshpam_authctxt = authctxt; |
147 |
157 |
148 if (sshpam_err != PAM_SUCCESS) { |
158 if (sshpam_err != PAM_SUCCESS) { |
149 --- orig/auth.h Fri Jun 20 15:39:05 2014 |
159 --- orig/auth.h Mon Jan 26 18:02:11 2015 |
150 +++ new/auth.h Fri Jun 20 15:39:05 2014 |
160 +++ new/auth.h Mon Jan 26 18:02:11 2015 |
151 @@ -76,6 +76,9 @@ |
161 @@ -76,6 +76,9 @@ |
152 #endif |
162 #endif |
153 Buffer *loginmsg; |
163 Buffer *loginmsg; |
154 void *methoddata; |
164 void *methoddata; |
155 +#ifdef PAM_ENHANCEMENT |
165 +#ifdef PAM_ENHANCEMENT |
156 + char *authmethod_name; |
166 + char *authmethod_name; |
157 +#endif |
167 +#endif |
158 }; |
168 }; |
159 /* |
169 /* |
160 * Every authentication method has to handle authentication requests for |
170 * Every authentication method has to handle authentication requests for |
161 --- orig/auth2.c Fri Jun 20 15:39:05 2014 |
171 --- orig/auth2.c Mon Jan 26 18:02:10 2015 |
162 +++ new/auth2.c Fri Jun 20 15:39:05 2014 |
172 +++ new/auth2.c Tue Mar 31 15:19:10 2015 |
163 @@ -249,10 +249,13 @@ |
173 @@ -249,10 +249,21 @@ |
164 PRIVSEP(audit_event(SSH_INVALID_USER)); |
174 PRIVSEP(audit_event(SSH_INVALID_USER)); |
165 #endif |
175 #endif |
166 } |
176 } |
167 + |
177 + |
168 +#ifndef PAM_ENHANCEMENT |
178 + |
169 #ifdef USE_PAM |
179 #ifdef USE_PAM |
|
180 +#ifdef PAM_ENHANCEMENT |
|
181 + /* |
|
182 + * Start PAM here and once only, if each userauth does not |
|
183 + * has its own PAM service. |
|
184 + */ |
|
185 + if (options.use_pam && !options.pam_service_per_authmethod) |
|
186 + PRIVSEP(start_pam(authctxt)); |
|
187 +#else |
170 if (options.use_pam) |
188 if (options.use_pam) |
171 PRIVSEP(start_pam(authctxt)); |
189 PRIVSEP(start_pam(authctxt)); |
172 #endif |
190 #endif |
173 +#endif |
191 +#endif |
174 setproctitle("%s%s", authctxt->valid ? user : "unknown", |
192 setproctitle("%s%s", authctxt->valid ? user : "unknown", |
175 use_privsep ? " [net]" : ""); |
193 use_privsep ? " [net]" : ""); |
176 authctxt->service = xstrdup(service); |
194 authctxt->service = xstrdup(service); |
177 @@ -286,6 +289,14 @@ |
195 @@ -286,6 +297,18 @@ |
178 /* try to authenticate user */ |
196 /* try to authenticate user */ |
179 m = authmethod_lookup(authctxt, method); |
197 m = authmethod_lookup(authctxt, method); |
180 if (m != NULL && authctxt->failures < options.max_authtries) { |
198 if (m != NULL && authctxt->failures < options.max_authtries) { |
181 + |
199 + |
182 +#ifdef PAM_ENHANCEMENT |
200 +#if defined(USE_PAM) && defined(PAM_ENHANCEMENT) |
183 + authctxt->authmethod_name = xstrdup(method); |
201 + /* start PAM service for each userauth */ |
184 + if (use_privsep) |
202 + if (options.use_pam && options.pam_service_per_authmethod) { |
185 + mm_inform_authmethod(method); |
203 + if (authctxt->authmethod_name != NULL) |
186 + if (options.use_pam) |
204 + free(authctxt->authmethod_name); |
187 + PRIVSEP(start_pam(authctxt)); |
205 + authctxt->authmethod_name = xstrdup(method); |
|
206 + if (use_privsep) |
|
207 + mm_inform_authmethod(method); |
|
208 + PRIVSEP(start_pam(authctxt)); |
|
209 + } |
188 +#endif |
210 +#endif |
189 debug2("input_userauth_request: try method %s", method); |
211 debug2("input_userauth_request: try method %s", method); |
190 authenticated = m->userauth(authctxt); |
212 authenticated = m->userauth(authctxt); |
191 } |
213 } |
192 @@ -303,6 +314,10 @@ |
214 @@ -303,6 +326,10 @@ |
193 char *methods; |
215 char *methods; |
194 int partial = 0; |
216 int partial = 0; |
195 |
217 |
196 +#ifdef PAM_ENHANCEMENT |
218 +#ifdef PAM_ENHANCEMENT |
197 + debug3("%s: entering", __func__); |
219 + debug3("%s: entering", __func__); |
198 +#endif |
220 +#endif |
199 + |
221 + |
200 if (!authctxt->valid && authenticated) |
222 if (!authctxt->valid && authenticated) |
201 fatal("INTERNAL ERROR: authenticated invalid user %s", |
223 fatal("INTERNAL ERROR: authenticated invalid user %s", |
202 authctxt->user); |
224 authctxt->user); |
203 @@ -623,5 +638,3 @@ |
225 @@ -319,6 +346,25 @@ |
|
226 } |
|
227 |
|
228 if (authenticated && options.num_auth_methods != 0) { |
|
229 + |
|
230 +#if defined(USE_PAM) && defined(PAM_ENHANCEMENT) |
|
231 + /* |
|
232 + * If each userauth has its own PAM service, then PAM need to |
|
233 + * perform account check for this service. |
|
234 + */ |
|
235 + if (options.use_pam && options.pam_service_per_authmethod && |
|
236 + !PRIVSEP(do_pam_account())) { |
|
237 + /* if PAM returned a message, send it to the user */ |
|
238 + if (buffer_len(&loginmsg) > 0) { |
|
239 + buffer_append(&loginmsg, "\0", 1); |
|
240 + userauth_send_banner(buffer_ptr(&loginmsg)); |
|
241 + packet_write_wait(); |
|
242 + } |
|
243 + |
|
244 + fatal("Access denied for user %s by PAM account " |
|
245 + "configuration", authctxt->user); |
|
246 + } |
|
247 +#endif |
|
248 if (!auth2_update_methods_lists(authctxt, method, submethod)) { |
|
249 authenticated = 0; |
|
250 partial = 1; |
|
251 @@ -332,7 +378,20 @@ |
|
252 return; |
|
253 |
|
254 #ifdef USE_PAM |
|
255 + |
|
256 +#ifdef PAM_ENHANCEMENT |
|
257 + /* |
|
258 + * PAM needs to perform account checks after auth. However, if each |
|
259 + * userauth has its own PAM service and options.num_auth_methods != 0, |
|
260 + * then no need to perform account checking, because it was done |
|
261 + * already. |
|
262 + */ |
|
263 + if (options.use_pam && authenticated && |
|
264 + !(options.num_auth_methods != 0 && |
|
265 + options.pam_service_per_authmethod)){ |
|
266 +#else |
|
267 if (options.use_pam && authenticated) { |
|
268 +#endif |
|
269 if (!PRIVSEP(do_pam_account())) { |
|
270 /* if PAM returned a message, send it to the user */ |
|
271 if (buffer_len(&loginmsg) > 0) { |
|
272 @@ -623,5 +682,3 @@ |
204 fatal("%s: method not in AuthenticationMethods", __func__); |
273 fatal("%s: method not in AuthenticationMethods", __func__); |
205 return 0; |
274 return 0; |
206 } |
275 } |
207 - |
276 - |
208 - |
277 - |
209 --- orig/monitor_wrap.c Fri Jun 20 15:39:05 2014 |
278 --- orig/monitor_wrap.c Mon Jan 26 18:02:09 2015 |
210 +++ new/monitor_wrap.c Fri Jun 20 15:39:05 2014 |
279 +++ new/monitor_wrap.c Mon Jan 26 18:02:11 2015 |
211 @@ -338,6 +338,24 @@ |
280 @@ -338,6 +338,24 @@ |
212 buffer_free(&m); |
281 buffer_free(&m); |
213 } |
282 } |
214 |
283 |
215 +#ifdef PAM_ENHANCEMENT |
284 +#ifdef PAM_ENHANCEMENT |
261 {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, |
330 {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, |
262 +#endif |
331 +#endif |
263 {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, |
332 {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, |
264 {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, |
333 {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, |
265 {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, |
334 {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, |
266 @@ -828,6 +838,10 @@ |
335 @@ -391,6 +401,24 @@ |
|
336 if (!compat20) |
|
337 fatal("AuthenticationMethods is not supported" |
|
338 "with SSH protocol 1"); |
|
339 + |
|
340 +#if defined(USE_PAM) && defined(PAM_ENHANCEMENT) |
|
341 + /* |
|
342 + * If each userauth has its own PAM service, then PAM |
|
343 + * need to perform account check for this service. |
|
344 + */ |
|
345 + if (options.use_pam && authenticated && |
|
346 + options.pam_service_per_authmethod) { |
|
347 + Buffer m; |
|
348 + |
|
349 + buffer_init(&m); |
|
350 + mm_request_receive_expect(pmonitor->m_sendfd, |
|
351 + MONITOR_REQ_PAM_ACCOUNT, &m); |
|
352 + authenticated = |
|
353 + mm_answer_pam_account(pmonitor->m_sendfd, &m); |
|
354 + buffer_free(&m); |
|
355 + } |
|
356 +#endif |
|
357 if (authenticated && |
|
358 !auth2_update_methods_lists(authctxt, |
|
359 auth_method, auth_submethod)) { |
|
360 @@ -409,8 +437,21 @@ |
|
361 !auth_root_allowed(auth_method)) |
|
362 authenticated = 0; |
|
363 #ifdef USE_PAM |
|
364 +#ifdef PAM_ENHANCEMENT |
|
365 + /* |
|
366 + * PAM needs to perform account checks after auth. |
|
367 + * However, if each userauth has its own PAM service |
|
368 + * and options.num_auth_methods != 0, then no need to |
|
369 + * perform account checking, because it was done |
|
370 + * already. |
|
371 + */ |
|
372 + if (options.use_pam && authenticated && |
|
373 + !(options.num_auth_methods != 0 && |
|
374 + options.pam_service_per_authmethod)) { |
|
375 +#else |
|
376 /* PAM needs to perform account checks after auth */ |
|
377 if (options.use_pam && authenticated) { |
|
378 +#endif |
|
379 Buffer m; |
|
380 |
|
381 buffer_init(&m); |
|
382 @@ -828,6 +869,10 @@ |
267 /* Allow service/style information on the auth context */ |
383 /* Allow service/style information on the auth context */ |
268 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); |
384 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); |
269 monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); |
385 monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); |
270 +#ifdef PAM_ENHANCEMENT |
386 +#ifdef PAM_ENHANCEMENT |
271 + /* Allow authmethod information on the auth context */ |
387 + /* Allow authmethod information on the auth context */ |
272 + monitor_permit(mon_dispatch, MONITOR_REQ_AUTHMETHOD, 1); |
388 + monitor_permit(mon_dispatch, MONITOR_REQ_AUTHMETHOD, 1); |
273 +#endif |
389 +#endif |
274 } |
390 } |
275 #ifdef USE_PAM |
391 #ifdef USE_PAM |
276 if (options.use_pam) |
392 if (options.use_pam) |
277 @@ -868,7 +882,25 @@ |
393 @@ -868,7 +913,25 @@ |
278 return (0); |
394 return (0); |
279 } |
395 } |
280 |
396 |
281 +#ifdef PAM_ENHANCEMENT |
397 +#ifdef PAM_ENHANCEMENT |
282 int |
398 int |
298 + |
414 + |
299 +int |
415 +int |
300 mm_answer_authpassword(int sock, Buffer *m) |
416 mm_answer_authpassword(int sock, Buffer *m) |
301 { |
417 { |
302 static int call_count; |
418 static int call_count; |
303 --- orig/monitor.h Fri Jun 20 15:39:05 2014 |
419 --- orig/monitor.h Mon Jan 26 18:02:10 2015 |
304 +++ new/monitor.h Fri Jun 20 15:39:05 2014 |
420 +++ new/monitor.h Mon Jan 26 18:02:11 2015 |
305 @@ -70,6 +70,9 @@ |
421 @@ -70,6 +70,9 @@ |
306 MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, |
422 MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, |
307 MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113, |
423 MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113, |
308 |
424 |
309 +#ifdef PAM_ENHANCEMENT |
425 +#ifdef PAM_ENHANCEMENT |
310 + MONITOR_REQ_AUTHMETHOD = 114, |
426 + MONITOR_REQ_AUTHMETHOD = 114, |
311 +#endif |
427 +#endif |
312 }; |
428 }; |
313 |
429 |
314 struct mm_master; |
430 struct mm_master; |
315 --- orig/servconf.c Fri Jun 20 15:39:05 2014 |
431 --- orig/servconf.c Mon Jan 26 18:02:09 2015 |
316 +++ new/servconf.c Fri Jun 20 15:39:05 2014 |
432 +++ new/servconf.c Tue Mar 31 16:24:59 2015 |
317 @@ -154,6 +154,10 @@ |
433 @@ -154,6 +154,18 @@ |
318 options->ip_qos_interactive = -1; |
434 options->ip_qos_interactive = -1; |
319 options->ip_qos_bulk = -1; |
435 options->ip_qos_bulk = -1; |
320 options->version_addendum = NULL; |
436 options->version_addendum = NULL; |
321 +#ifdef PAM_ENHANCEMENT |
437 +#ifdef PAM_ENHANCEMENT |
322 + options->pam_service_name = NULL; |
438 + options->pam_service_name = NULL; |
323 + options->pam_service_prefix = NULL; |
439 + options->pam_service_prefix = NULL; |
|
440 + |
|
441 + /* |
|
442 + * Each user method will have its own PAM service by default. |
|
443 + * However, if PAMServiceName is specified or the protocal version |
|
444 + * is not compat20, then there will be only one PAM service for the |
|
445 + * entire user authentication. |
|
446 + */ |
|
447 + options->pam_service_per_authmethod = 1; |
324 +#endif |
448 +#endif |
325 } |
449 } |
326 |
450 |
327 void |
451 void |
328 @@ -303,6 +307,12 @@ |
452 @@ -303,6 +315,12 @@ |
329 options->ip_qos_bulk = IPTOS_THROUGHPUT; |
453 options->ip_qos_bulk = IPTOS_THROUGHPUT; |
330 if (options->version_addendum == NULL) |
454 if (options->version_addendum == NULL) |
331 options->version_addendum = xstrdup(""); |
455 options->version_addendum = xstrdup(""); |
332 + |
456 + |
333 +#ifdef PAM_ENHANCEMENT |
457 +#ifdef PAM_ENHANCEMENT |
336 +#endif |
460 +#endif |
337 + |
461 + |
338 /* Turn privilege separation on by default */ |
462 /* Turn privilege separation on by default */ |
339 if (use_privsep == -1) |
463 if (use_privsep == -1) |
340 use_privsep = PRIVSEP_NOSANDBOX; |
464 use_privsep = PRIVSEP_NOSANDBOX; |
341 @@ -351,6 +361,9 @@ |
465 @@ -351,6 +369,9 @@ |
342 sKexAlgorithms, sIPQoS, sVersionAddendum, |
466 sKexAlgorithms, sIPQoS, sVersionAddendum, |
343 sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, |
467 sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, |
344 sAuthenticationMethods, sHostKeyAgent, |
468 sAuthenticationMethods, sHostKeyAgent, |
345 +#ifdef PAM_ENHANCEMENT |
469 +#ifdef PAM_ENHANCEMENT |
346 + sPAMServicePrefix, sPAMServiceName, |
470 + sPAMServicePrefix, sPAMServiceName, |
347 +#endif |
471 +#endif |
348 sDeprecated, sUnsupported |
472 sDeprecated, sUnsupported |
349 } ServerOpCodes; |
473 } ServerOpCodes; |
350 |
474 |
351 @@ -482,6 +495,10 @@ |
475 @@ -482,6 +503,10 @@ |
352 { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, |
476 { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, |
353 { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, |
477 { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, |
354 { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, |
478 { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, |
355 +#ifdef PAM_ENHANCEMENT |
479 +#ifdef PAM_ENHANCEMENT |
356 + { "pamserviceprefix", sPAMServicePrefix, SSHCFG_GLOBAL }, |
480 + { "pamserviceprefix", sPAMServicePrefix, SSHCFG_GLOBAL }, |
357 + { "pamservicename", sPAMServiceName, SSHCFG_GLOBAL }, |
481 + { "pamservicename", sPAMServiceName, SSHCFG_GLOBAL }, |
358 +#endif |
482 +#endif |
359 { NULL, sBadOption, 0 } |
483 { NULL, sBadOption, 0 } |
360 }; |
484 }; |
361 |
485 |
362 @@ -1632,6 +1649,30 @@ |
486 @@ -1632,6 +1657,37 @@ |
363 } |
487 } |
364 return 0; |
488 return 0; |
365 |
489 |
366 + case sPAMServicePrefix: |
490 + case sPAMServicePrefix: |
367 + arg = strdelim(&cp); |
491 + arg = strdelim(&cp); |
381 + fatal("%s line %d: Missing argument.", |
505 + fatal("%s line %d: Missing argument.", |
382 + filename, linenum); |
506 + filename, linenum); |
383 + if (options->pam_service_prefix != NULL) |
507 + if (options->pam_service_prefix != NULL) |
384 + fatal("%s line %d: PAMServiceName and PAMServicePrefix" |
508 + fatal("%s line %d: PAMServiceName and PAMServicePrefix" |
385 + " are mutually exclusive.", filename, linenum); |
509 + " are mutually exclusive.", filename, linenum); |
386 + if (options->pam_service_name == NULL) |
510 + if (options->pam_service_name == NULL) { |
387 + options->pam_service_name = xstrdup(arg); |
511 + options->pam_service_name = xstrdup(arg); |
|
512 + |
|
513 + /* |
|
514 + * When this option is specified, we will not have |
|
515 + * PAM service for each auth method. |
|
516 + */ |
|
517 + options->pam_service_per_authmethod = 0; |
|
518 + } |
388 + break; |
519 + break; |
389 + |
520 + |
390 case sDeprecated: |
521 case sDeprecated: |
391 logit("%s line %d: Deprecated option %s", |
522 logit("%s line %d: Deprecated option %s", |
392 filename, linenum, arg); |
523 filename, linenum, arg); |
393 --- orig/servconf.h Fri Jun 20 15:39:05 2014 |
524 --- orig/servconf.h Mon Jan 26 18:02:10 2015 |
394 +++ new/servconf.h Fri Jun 20 15:39:05 2014 |
525 +++ new/servconf.h Tue Mar 31 15:07:14 2015 |
395 @@ -54,6 +54,10 @@ |
526 @@ -54,6 +54,10 @@ |
396 /* Magic name for internal sftp-server */ |
527 /* Magic name for internal sftp-server */ |
397 #define INTERNAL_SFTP_NAME "internal-sftp" |
528 #define INTERNAL_SFTP_NAME "internal-sftp" |
398 |
529 |
399 +#ifdef PAM_ENHANCEMENT |
530 +#ifdef PAM_ENHANCEMENT |