View | Details | Raw Unified | Return to bug 2548 | Differences between
and this patch

Collapse All | Expand All

(-)a/auth-pam.c (-243 / +158 lines)
Lines 98-103 Link Here
98
#include "ssh-gss.h"
98
#include "ssh-gss.h"
99
#endif
99
#endif
100
#include "monitor_wrap.h"
100
#include "monitor_wrap.h"
101
#include "ssherr.h"
101
102
102
extern ServerOptions options;
103
extern ServerOptions options;
103
extern Buffer loginmsg;
104
extern Buffer loginmsg;
Lines 110-147 extern u_int utmp_len; Link Here
110
#endif
111
#endif
111
112
112
/*
113
/*
113
 * Formerly known as USE_POSIX_THREADS, using this is completely unsupported
114
 * PAM processing model has been rewritten.
114
 * and generally a bad idea.  Use at own risk and do not expect support if
115
 * Now all the calls to PAM are within the monitor process,
115
 * this breaks.
116
 * pam_get_data/pam_set_data works as designed and there is no need
117
 * for the threads anymore.
116
 */
118
 */
117
#ifdef UNSUPPORTED_POSIX_THREADS_HACK
119
#ifdef UNSUPPORTED_POSIX_THREADS_HACK
118
#include <pthread.h>
120
# error "UNSUPPORTED_POSIX_THREADS_HACK no longer supported"
119
/*
120
 * Avoid namespace clash when *not* using pthreads for systems *with*
121
 * pthreads, which unconditionally define pthread_t via sys/types.h
122
 * (e.g. Linux)
123
 */
124
typedef pthread_t sp_pthread_t;
125
#else
126
typedef pid_t sp_pthread_t;
127
#endif
121
#endif
128
122
129
struct pam_ctxt {
123
struct pam_ctxt {
130
	sp_pthread_t	 pam_thread;
124
	pid_t	 pam_child;
131
	int		 pam_psock;
125
	int	 pam_psock;
132
	int		 pam_csock;
126
	int	 pam_csock;
133
	int		 pam_done;
127
	int	 pam_done;
134
};
128
};
135
129
136
static void sshpam_free_ctx(void *);
130
static void sshpam_free_ctx(void *);
137
static struct pam_ctxt *cleanup_ctxt;
131
static struct pam_ctxt *cleanup_ctxt;
138
132
139
#ifndef UNSUPPORTED_POSIX_THREADS_HACK
133
static int sshpam_child_status = -1;
140
/*
141
 * Simulate threads with processes.
142
 */
143
144
static int sshpam_thread_status = -1;
145
static mysig_t sshpam_oldsig;
134
static mysig_t sshpam_oldsig;
146
135
147
static void
136
static void
Lines 150-227 sshpam_sigchld_handler(int sig) Link Here
150
	signal(SIGCHLD, SIG_DFL);
139
	signal(SIGCHLD, SIG_DFL);
151
	if (cleanup_ctxt == NULL)
140
	if (cleanup_ctxt == NULL)
152
		return;	/* handler called after PAM cleanup, shouldn't happen */
141
		return;	/* handler called after PAM cleanup, shouldn't happen */
153
	if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, WNOHANG)
142
	if (waitpid(cleanup_ctxt->pam_child, &sshpam_child_status, WNOHANG)
154
	    <= 0) {
143
	    <= 0) {
155
		/* PAM thread has not exitted, privsep slave must have */
144
		/* callback child has not exitted, privsep slave must have */
156
		kill(cleanup_ctxt->pam_thread, SIGTERM);
145
		kill(cleanup_ctxt->pam_child, SIGTERM);
157
		if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0)
146
		if (waitpid(cleanup_ctxt->pam_child, &sshpam_child_status, 0)
158
		    <= 0)
147
		    <= 0)
159
			return; /* could not wait */
148
			return; /* could not wait */
160
	}
149
	}
161
	if (WIFSIGNALED(sshpam_thread_status) &&
150
	if (WIFSIGNALED(sshpam_child_status) &&
162
	    WTERMSIG(sshpam_thread_status) == SIGTERM)
151
	    WTERMSIG(sshpam_child_status) == SIGTERM)
163
		return;	/* terminated by pthread_cancel */
152
		return;
164
	if (!WIFEXITED(sshpam_thread_status))
153
	if (!WIFEXITED(sshpam_child_status))
165
		sigdie("PAM: authentication thread exited unexpectedly");
154
		sigdie("PAM: callback child exited unexpectedly");
166
	if (WEXITSTATUS(sshpam_thread_status) != 0)
155
	if (WEXITSTATUS(sshpam_child_status) != 0)
167
		sigdie("PAM: authentication thread exited uncleanly");
156
		sigdie("PAM: callback child exited uncleanly");
168
}
169
170
/* ARGSUSED */
171
static void
172
pthread_exit(void *value)
173
{
174
	_exit(0);
175
}
176
177
/* ARGSUSED */
178
static int
179
pthread_create(sp_pthread_t *thread, const void *attr,
180
    void *(*thread_start)(void *), void *arg)
181
{
182
	pid_t pid;
183
	struct pam_ctxt *ctx = arg;
184
185
	sshpam_thread_status = -1;
186
	switch ((pid = fork())) {
187
	case -1:
188
		error("fork(): %s", strerror(errno));
189
		return (-1);
190
	case 0:
191
		close(ctx->pam_psock);
192
		ctx->pam_psock = -1;
193
		thread_start(arg);
194
		_exit(1);
195
	default:
196
		*thread = pid;
197
		close(ctx->pam_csock);
198
		ctx->pam_csock = -1;
199
		sshpam_oldsig = signal(SIGCHLD, sshpam_sigchld_handler);
200
		return (0);
201
	}
202
}
203
204
static int
205
pthread_cancel(sp_pthread_t thread)
206
{
207
	signal(SIGCHLD, sshpam_oldsig);
208
	return (kill(thread, SIGTERM));
209
}
210
211
/* ARGSUSED */
212
static int
213
pthread_join(sp_pthread_t thread, void **value)
214
{
215
	int status;
216
217
	if (sshpam_thread_status != -1)
218
		return (sshpam_thread_status);
219
	signal(SIGCHLD, sshpam_oldsig);
220
	waitpid(thread, &status, 0);
221
	return (status);
222
}
157
}
223
#endif
224
225
158
226
static pam_handle_t *sshpam_handle = NULL;
159
static pam_handle_t *sshpam_handle = NULL;
227
static int sshpam_err = 0;
160
static int sshpam_err = 0;
Lines 291-345 sshpam_password_change_required(int reqd) Link Here
291
	}
224
	}
292
}
225
}
293
226
294
/* Import regular and PAM environment from subprocess */
295
static void
296
import_environments(Buffer *b)
297
{
298
	char *env;
299
	u_int i, num_env;
300
	int err;
301
302
	debug3("PAM: %s entering", __func__);
303
304
#ifndef UNSUPPORTED_POSIX_THREADS_HACK
305
	/* Import variables set by do_pam_account */
306
	sshpam_account_status = buffer_get_int(b);
307
	sshpam_password_change_required(buffer_get_int(b));
308
309
	/* Import environment from subprocess */
310
	num_env = buffer_get_int(b);
311
	if (num_env > 1024)
312
		fatal("%s: received %u environment variables, expected <= 1024",
313
		    __func__, num_env);
314
	sshpam_env = xcalloc(num_env + 1, sizeof(*sshpam_env));
315
	debug3("PAM: num env strings %d", num_env);
316
	for(i = 0; i < num_env; i++)
317
		sshpam_env[i] = buffer_get_string(b, NULL);
318
319
	sshpam_env[num_env] = NULL;
320
321
	/* Import PAM environment from subprocess */
322
	num_env = buffer_get_int(b);
323
	debug("PAM: num PAM env strings %d", num_env);
324
	for(i = 0; i < num_env; i++) {
325
		env = buffer_get_string(b, NULL);
326
327
#ifdef HAVE_PAM_PUTENV
328
		/* Errors are not fatal here */
329
		if ((err = pam_putenv(sshpam_handle, env)) != PAM_SUCCESS) {
330
			error("PAM: pam_putenv: %s",
331
			    pam_strerror(sshpam_handle, sshpam_err));
332
		}
333
#endif
334
	}
335
#endif
336
}
337
338
/*
227
/*
339
 * Conversation function for authentication thread.
228
 * Conversation function for keyboard-interactive authentication.
340
 */
229
 */
341
static int
230
static int
342
sshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
231
sshpam_child_conv(int n, sshpam_const struct pam_message **msg,
343
    struct pam_response **resp, void *data)
232
    struct pam_response **resp, void *data)
344
{
233
{
345
	Buffer buffer;
234
	Buffer buffer;
Lines 421-468 sshpam_thread_conv(int n, sshpam_const struct pam_message **msg, Link Here
421
}
310
}
422
311
423
/*
312
/*
424
 * Authentication thread.
313
 * Terminates the call back child.
314
 *
315
 * Sends a message of type PAM_SUCCESS or PAM_AUTH_ERR to the child.
316
 * In response receives a message with remaining PAM prompts.
317
 * When not using privilege separation, receives serialized packet state too.
318
 *
319
 * After that, the child exits.
425
 */
320
 */
426
static void *
321
void
427
sshpam_thread(void *ctxtp)
322
relieve_from_duty(struct pam_ctxt *ctxt)
428
{
323
{
429
	struct pam_ctxt *ctxt = ctxtp;
430
	Buffer buffer;
324
	Buffer buffer;
431
	struct pam_conv sshpam_conv;
325
	struct ssh *ssh = active_state;
432
	int flags = (options.permit_empty_passwd == 0 ?
326
	int r;
433
	    PAM_DISALLOW_NULL_AUTHTOK : 0);
327
	u_char type;
434
#ifndef UNSUPPORTED_POSIX_THREADS_HACK
328
	char *msg;
435
	extern char **environ;
329
	u_int len;
436
	char **env_from_pam;
437
	u_int i;
438
	const char *pam_user;
439
	const char **ptr_pam_user = &pam_user;
440
	char *tz = getenv("TZ");
441
442
	sshpam_err = pam_get_item(sshpam_handle, PAM_USER,
443
	    (sshpam_const void **)ptr_pam_user);
444
	if (sshpam_err != PAM_SUCCESS)
445
		goto auth_fail;
446
330
447
	environ[0] = NULL;
331
	buffer_init(&buffer);
448
	if (tz != NULL)
332
	buffer_put_cstring(&buffer, "OK");
449
		if (setenv("TZ", tz, 1) == -1)
333
	type = (ctxt->pam_done == 1) ? PAM_SUCCESS : PAM_AUTH_ERR;
450
			error("PAM: could not set TZ environment: %s",
334
	if (ssh_msg_send(ctxt->pam_csock, type, &buffer) == -1) {
451
			    strerror(errno));
335
		buffer_free(&buffer);
336
		fatal("%s: cannnot terminate callback child (send)", __func__);
337
	}
452
338
453
	if (sshpam_authctxt != NULL) {
339
	buffer_clear(&buffer);
454
		setproctitle("%s [pam]",
340
	if (ssh_msg_recv(ctxt->pam_csock, &buffer) == -1) {
455
		    sshpam_authctxt->valid ? pam_user : "unknown");
341
		buffer_free(&buffer);
342
		fatal("%s: cannnot terminate callback child (receive)",
343
		    __func__);
456
	}
344
	}
457
#endif
345
	type = buffer_get_char(&buffer);
346
	msg = buffer_get_cstring(&buffer, &len);
347
	if(len)
348
		buffer_append(&loginmsg, msg, len);
349
	/* if not using privsep child, sync packet state from callback child */	
350
	if (!use_privsep) {
351
		if ((r = ssh_packet_set_state(ssh, &buffer)) != 0)
352
			fatal("%s: set_state failed: %s",
353
			   __func__, ssh_err(r));
354
	}
355
	free(msg);
356
	buffer_free(&buffer);
357
	close(ctxt->pam_csock);
358
	ctxt->pam_csock = -1;
359
}
360
361
int
362
get_pam_done(void *ctxt)
363
{
364
	struct pam_ctxt *pctxt = (struct pam_ctxt *)ctxt;
365
	return (pctxt->pam_done);
366
}
458
367
459
	sshpam_conv.conv = sshpam_thread_conv;
368
/*
369
 * Perform PAM authentication.
370
 *
371
 * PAM APIs (pam_authenticate, pam_acct_mgmt, ...) block and call the
372
 * provided callback conversation function (sshpam_conv). The conversation
373
 * function sends messages to the callback child (pam_ctxt.pam_child), which
374
 * communicates with the client directly, or indirectly through privsep child.
375
 */
376
void
377
do_pam_auth(struct pam_ctxt *ctxt)
378
{
379
	struct pam_conv sshpam_conv;
380
	int flags = (options.permit_empty_passwd == 0 ?
381
	    PAM_DISALLOW_NULL_AUTHTOK : 0);
382
383
	sshpam_conv.conv = sshpam_child_conv;
460
	sshpam_conv.appdata_ptr = ctxt;
384
	sshpam_conv.appdata_ptr = ctxt;
461
385
386
	ctxt->pam_done = -1;
387
462
	if (sshpam_authctxt == NULL)
388
	if (sshpam_authctxt == NULL)
463
		fatal("%s: PAM authctxt not initialized", __func__);
389
		fatal("%s: PAM authctxt not initialized", __func__);
464
390
465
	buffer_init(&buffer);
466
	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
391
	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
467
	    (const void *)&sshpam_conv);
392
	    (const void *)&sshpam_conv);
468
	if (sshpam_err != PAM_SUCCESS)
393
	if (sshpam_err != PAM_SUCCESS)
Lines 485-544 sshpam_thread(void *ctxtp) Link Here
485
		}
410
		}
486
	}
411
	}
487
412
488
	buffer_put_cstring(&buffer, "OK");
413
	ctxt->pam_done = 1;
489
490
#ifndef UNSUPPORTED_POSIX_THREADS_HACK
491
	/* Export variables set by do_pam_account */
492
	buffer_put_int(&buffer, sshpam_account_status);
493
	buffer_put_int(&buffer, sshpam_authctxt->force_pwchange);
494
495
	/* Export any environment strings set in child */
496
	for(i = 0; environ[i] != NULL; i++)
497
		; /* Count */
498
	buffer_put_int(&buffer, i);
499
	for(i = 0; environ[i] != NULL; i++)
500
		buffer_put_cstring(&buffer, environ[i]);
501
502
	/* Export any environment strings set by PAM in child */
503
	env_from_pam = pam_getenvlist(sshpam_handle);
504
	for(i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++)
505
		; /* Count */
506
	buffer_put_int(&buffer, i);
507
	for(i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++)
508
		buffer_put_cstring(&buffer, env_from_pam[i]);
509
#endif /* UNSUPPORTED_POSIX_THREADS_HACK */
510
511
	/* XXX - can't do much about an error here */
512
	ssh_msg_send(ctxt->pam_csock, sshpam_err, &buffer);
513
	buffer_free(&buffer);
514
	pthread_exit(NULL);
515
414
516
 auth_fail:
415
 auth_fail:
517
	buffer_put_cstring(&buffer,
416
	if (sshpam_err != PAM_SUCCESS)
518
	    pam_strerror(sshpam_handle, sshpam_err));
417
		error("PAM: %s for %s%.100s from %.100s",
519
	/* XXX - can't do much about an error here */
418
		    pam_strerror(sshpam_handle, sshpam_err),
520
	if (sshpam_err == PAM_ACCT_EXPIRED)
419
		    sshpam_authctxt->valid ? "" : "illegal user ",
521
		ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, &buffer);
420
		    sshpam_authctxt->user,
522
	else
421
		    get_remote_name_or_ip(utmp_len, options.use_dns));
523
		ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer);
422
	relieve_from_duty(ctxt);
524
	buffer_free(&buffer);
525
	pthread_exit(NULL);
526
527
	return (NULL); /* Avoid warning for non-pthread case */
528
}
423
}
529
424
530
void
425
void
531
sshpam_thread_cleanup(void)
426
sshpam_child_cleanup(void)
532
{
427
{
533
	struct pam_ctxt *ctxt = cleanup_ctxt;
428
	struct pam_ctxt *ctxt = cleanup_ctxt;
534
429
535
	debug3("PAM: %s entering", __func__);
430
	debug3("PAM: %s entering", __func__);
536
	if (ctxt != NULL && ctxt->pam_thread != 0) {
431
	if (ctxt != NULL && ctxt->pam_child != 0) {
537
		pthread_cancel(ctxt->pam_thread);
432
		signal(SIGCHLD, sshpam_oldsig);
538
		pthread_join(ctxt->pam_thread, NULL);
433
		/* callback child should have had exited by now */
539
		close(ctxt->pam_psock);
434
		kill(ctxt->pam_child, SIGTERM);
540
		close(ctxt->pam_csock);
435
		if (ctxt->pam_psock != -1)
541
		memset(ctxt, 0, sizeof(*ctxt));
436
			close(ctxt->pam_psock);
437
		if (ctxt->pam_csock != -1)
438
			close(ctxt->pam_csock);
439
		if (sshpam_child_status == -1)
440
			waitpid(ctxt->pam_child, &sshpam_child_status, 0);
542
		cleanup_ctxt = NULL;
441
		cleanup_ctxt = NULL;
543
	}
442
	}
544
}
443
}
Lines 674-679 sshpam_init_ctx(Authctxt *authctxt) Link Here
674
{
573
{
675
	struct pam_ctxt *ctxt;
574
	struct pam_ctxt *ctxt;
676
	int socks[2];
575
	int socks[2];
576
	pid_t pid;
677
577
678
	debug3("PAM: %s entering", __func__);
578
	debug3("PAM: %s entering", __func__);
679
	/*
579
	/*
Lines 691-697 sshpam_init_ctx(Authctxt *authctxt) Link Here
691
591
692
	ctxt = xcalloc(1, sizeof *ctxt);
592
	ctxt = xcalloc(1, sizeof *ctxt);
693
593
694
	/* Start the authentication thread */
594
	/* Fork the callback child and start PAM authentication */
695
	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socks) == -1) {
595
	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socks) == -1) {
696
		error("PAM: failed create sockets: %s", strerror(errno));
596
		error("PAM: failed create sockets: %s", strerror(errno));
697
		free(ctxt);
597
		free(ctxt);
Lines 699-713 sshpam_init_ctx(Authctxt *authctxt) Link Here
699
	}
599
	}
700
	ctxt->pam_psock = socks[0];
600
	ctxt->pam_psock = socks[0];
701
	ctxt->pam_csock = socks[1];
601
	ctxt->pam_csock = socks[1];
702
	if (pthread_create(&ctxt->pam_thread, NULL, sshpam_thread, ctxt) == -1) {
602
703
		error("PAM: failed to start authentication thread: %s",
603
	sshpam_child_status = -1;
704
		    strerror(errno));
604
	switch ((pid = fork())) {
605
	case -1:
606
		error("fork(): %s", strerror(errno));
705
		close(socks[0]);
607
		close(socks[0]);
706
		close(socks[1]);
608
		close(socks[1]);
707
		free(ctxt);
609
		free(ctxt);
708
		return (NULL);
610
		return (NULL);
611
	case 0:
612
		/* child processes query & respond for kbdint */
613
		close(ctxt->pam_csock);
614
		ctxt->pam_csock = -1;
615
		break;
616
	default:
617
		/* parent does PAM */
618
		ctxt->pam_child = pid;
619
		close(ctxt->pam_psock);
620
		ctxt->pam_psock = -1;
621
		sshpam_oldsig = signal(SIGCHLD, sshpam_sigchld_handler);
622
		cleanup_ctxt = ctxt;
623
		do_pam_auth(ctxt);
709
	}
624
	}
710
	cleanup_ctxt = ctxt;
711
	return (ctxt);
625
	return (ctxt);
712
}
626
}
713
627
Lines 721-728 sshpam_query(void *ctx, char **name, char **info, Link Here
721
	u_char type;
635
	u_char type;
722
	char *msg;
636
	char *msg;
723
	size_t len, mlen;
637
	size_t len, mlen;
638
	struct ssh *ssh;
639
	int r;
724
640
725
	debug3("PAM: %s entering", __func__);
641
	debug3("PAM: %s entering", __func__);
642
726
	buffer_init(&buffer);
643
	buffer_init(&buffer);
727
	*name = xstrdup("");
644
	*name = xstrdup("");
728
	*info = xstrdup("");
645
	*info = xstrdup("");
Lines 730-735 sshpam_query(void *ctx, char **name, char **info, Link Here
730
	**prompts = NULL;
647
	**prompts = NULL;
731
	plen = 0;
648
	plen = 0;
732
	*echo_on = xmalloc(sizeof(u_int));
649
	*echo_on = xmalloc(sizeof(u_int));
650
651
	/* in case PAM was already done in callback child */
652
	switch (ctxt->pam_done) {
653
	case 1:
654
		return (0);
655
	case 0:
656
		break;
657
	default:
658
		return (-1);
659
	}
660
733
	while (ssh_msg_recv(ctxt->pam_psock, &buffer) == 0) {
661
	while (ssh_msg_recv(ctxt->pam_psock, &buffer) == 0) {
734
		type = buffer_get_char(&buffer);
662
		type = buffer_get_char(&buffer);
735
		msg = buffer_get_string(&buffer, NULL);
663
		msg = buffer_get_string(&buffer, NULL);
Lines 761-775 sshpam_query(void *ctx, char **name, char **info, Link Here
761
			/* FALLTHROUGH */
689
			/* FALLTHROUGH */
762
		case PAM_AUTH_ERR:
690
		case PAM_AUTH_ERR:
763
			debug3("PAM: %s", pam_strerror(sshpam_handle, type));
691
			debug3("PAM: %s", pam_strerror(sshpam_handle, type));
764
			if (**prompts != NULL && strlen(**prompts) != 0) {
765
				*info = **prompts;
766
				**prompts = NULL;
767
				*num = 0;
768
				**echo_on = 0;
769
				ctxt->pam_done = -1;
770
				free(msg);
771
				return 0;
772
			}
773
			/* FALLTHROUGH */
692
			/* FALLTHROUGH */
774
		case PAM_SUCCESS:
693
		case PAM_SUCCESS:
775
			if (**prompts != NULL) {
694
			if (**prompts != NULL) {
Lines 780-804 sshpam_query(void *ctx, char **name, char **info, Link Here
780
				free(**prompts);
699
				free(**prompts);
781
				**prompts = NULL;
700
				**prompts = NULL;
782
			}
701
			}
783
			if (type == PAM_SUCCESS) {
702
			/* send accumulated messages to parent */
784
				if (!sshpam_authctxt->valid ||
703
			buffer_clear(&buffer);
785
				    (sshpam_authctxt->pw->pw_uid == 0 &&
704
			buffer_put_cstring(&buffer, buffer_ptr(&loginmsg));
786
				    options.permit_root_login != PERMIT_YES))
705
			if (!use_privsep) {
787
					fatal("Internal error: PAM auth "
706
				/* sync packet state with parrent */
788
					    "succeeded when it should have "
707
				ssh = active_state;
789
					    "failed");
708
				r = ssh_packet_get_state(ssh, &buffer);
790
				import_environments(&buffer);
709
				if (r != 0)
791
				*num = 0;
710
					fatal("%s: get_state failed: %s",
792
				**echo_on = 0;
711
					   __func__, ssh_err(r));
793
				ctxt->pam_done = 1;
794
				free(msg);
795
				return (0);
796
			}
712
			}
797
			error("PAM: %s for %s%.100s from %.100s", msg,
713
			ssh_msg_send(ctxt->pam_psock, type, &buffer);
798
			    sshpam_authctxt->valid ? "" : "illegal user ",
714
			/* callback child ends here */
799
			    sshpam_authctxt->user,
715
			close(ctxt->pam_psock);
800
			    get_remote_name_or_ip(utmp_len, options.use_dns));
716
			exit(0);
801
			/* FALLTHROUGH */
802
		default:
717
		default:
803
			*num = 0;
718
			*num = 0;
804
			**echo_on = 0;
719
			**echo_on = 0;
Lines 852-858 sshpam_free_ctx(void *ctxtp) Link Here
852
	struct pam_ctxt *ctxt = ctxtp;
767
	struct pam_ctxt *ctxt = ctxtp;
853
768
854
	debug3("PAM: %s entering", __func__);
769
	debug3("PAM: %s entering", __func__);
855
	sshpam_thread_cleanup();
770
	sshpam_child_cleanup();
856
	free(ctxt);
771
	free(ctxt);
857
	/*
772
	/*
858
	 * We don't call sshpam_cleanup() here because we may need the PAM
773
	 * We don't call sshpam_cleanup() here because we may need the PAM
(-)a/auth-pam.h (-1 / +2 lines)
Lines 42-50 int do_pam_putenv(char *, char *); Link Here
42
char ** fetch_pam_environment(void);
42
char ** fetch_pam_environment(void);
43
char ** fetch_pam_child_environment(void);
43
char ** fetch_pam_child_environment(void);
44
void free_pam_environment(char **);
44
void free_pam_environment(char **);
45
void sshpam_thread_cleanup(void);
45
void sshpam_child_cleanup(void);
46
void sshpam_cleanup(void);
46
void sshpam_cleanup(void);
47
int sshpam_auth_passwd(Authctxt *, const char *);
47
int sshpam_auth_passwd(Authctxt *, const char *);
48
int is_pam_session_open(void);
48
int is_pam_session_open(void);
49
int get_pam_done(void *);
49
50
50
#endif /* USE_PAM */
51
#endif /* USE_PAM */
(-)a/monitor.c (+18 lines)
Lines 1091-1096 mm_answer_pam_init_ctx(int sock, Buffer *m) Link Here
1091
	} else {
1091
	} else {
1092
		buffer_put_int(m, 0);
1092
		buffer_put_int(m, 0);
1093
	}
1093
	}
1094
1095
	/* pam conversation successfully finished in child process */
1096
	if(sshpam_ctxt && get_pam_done(sshpam_ctxt) != 0) {
1097
		auth_method = "keyboard-interactive";
1098
		auth_submethod = "pam";
1099
		/* 
1100
		 * ANS_PAM_INIT_CTX already sent by callback child.
1101
		 * Privsep child now expects ANS_PAM_QUERY.
1102
		 */
1103
		buffer_clear(m);
1104
		buffer_put_int(m, 0);		/* ret */
1105
		buffer_put_cstring(m, "");	/* name */
1106
		buffer_put_cstring(m, "");	/* info */
1107
		buffer_put_int(m, 0);		/* num */
1108
		mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m);
1109
		return (0);
1110
	}
1111
1094
	mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m);
1112
	mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m);
1095
	return (0);
1113
	return (0);
1096
}
1114
}
(-)a/servconf.c (+12 lines)
Lines 389-394 fill_default_server_options(ServerOptions *options) Link Here
389
		options->compression = 0;
389
		options->compression = 0;
390
	}
390
	}
391
#endif
391
#endif
392
#ifdef USE_PAM
393
	if (!use_privsep && options->compression == COMP_ZLIB && 
394
	    options->use_pam && 
395
	    (options->kbd_interactive_authentication || 
396
	     options->challenge_response_authentication)) {
397
		error("Compression algorithm 'zlib' is not supported for "
398
		    "PAM authentication when privilege separation is off");
399
		error("Limmiting compression algorithms to "
400
		    "'none,zlib@openssh.com'");
401
		options->compression = COMP_DELAYED;
402
	}
403
#endif
392
404
393
}
405
}
394
406
(-)a/session.c (-2 / +1 lines)
Lines 2744-2750 do_cleanup(Authctxt *authctxt) Link Here
2744
#ifdef USE_PAM
2744
#ifdef USE_PAM
2745
	if (options.use_pam) {
2745
	if (options.use_pam) {
2746
		sshpam_cleanup();
2746
		sshpam_cleanup();
2747
		sshpam_thread_cleanup();
2747
		sshpam_child_cleanup();
2748
	}
2748
	}
2749
#endif
2749
#endif
2750
2750
2751
- 

Return to bug 2548