View | Details | Raw Unified | Return to bug 2980
Collapse All | Expand All

(-)a/auth-pam.c (-45 / +92 lines)
Lines 239-244 pthread_join(sp_pthread_t thread, void **value) Link Here
239
239
240
240
241
static pam_handle_t *sshpam_handle = NULL;
241
static pam_handle_t *sshpam_handle = NULL;
242
static pam_handle_t *sshpam_password_handle = NULL;
242
static int sshpam_err = 0;
243
static int sshpam_err = 0;
243
static int sshpam_authenticated = 0;
244
static int sshpam_authenticated = 0;
244
static int sshpam_session_open = 0;
245
static int sshpam_session_open = 0;
Lines 652-704 static struct pam_conv store_conv = { sshpam_store_conv, NULL }; Link Here
652
void
653
void
653
sshpam_cleanup(void)
654
sshpam_cleanup(void)
654
{
655
{
655
	if (sshpam_handle == NULL || (use_privsep && !mm_is_monitor()))
656
	if (!(sshpam_handle == NULL || (use_privsep && !mm_is_monitor()))) {
656
		return;
657
		debug("PAM: cleanup");
657
	debug("PAM: cleanup");
658
		pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv);
658
	pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv);
659
		if (sshpam_session_open) {
659
	if (sshpam_session_open) {
660
			debug("PAM: closing session");
660
		debug("PAM: closing session");
661
			pam_close_session(sshpam_handle, PAM_SILENT);
661
		pam_close_session(sshpam_handle, PAM_SILENT);
662
			sshpam_session_open = 0;
662
		sshpam_session_open = 0;
663
		}
664
		if (sshpam_cred_established) {
665
			debug("PAM: deleting credentials");
666
			pam_setcred(sshpam_handle, PAM_DELETE_CRED);
667
			sshpam_cred_established = 0;
668
		}
669
		sshpam_authenticated = 0;
670
		pam_end(sshpam_handle, sshpam_err);
671
		sshpam_handle = NULL;
663
	}
672
	}
664
	if (sshpam_cred_established) {
673
	if (!(sshpam_password_handle == NULL)) {
665
		debug("PAM: deleting credentials");
674
		pam_end(sshpam_password_handle, sshpam_err);
666
		pam_setcred(sshpam_handle, PAM_DELETE_CRED);
675
		sshpam_password_handle = NULL;
667
		sshpam_cred_established = 0;
668
	}
676
	}
669
	sshpam_authenticated = 0;
670
	pam_end(sshpam_handle, sshpam_err);
671
	sshpam_handle = NULL;
672
}
677
}
673
678
674
static int
679
static int
675
sshpam_init(struct ssh *ssh, Authctxt *authctxt)
680
sshpam_init(struct ssh *ssh, Authctxt *authctxt, char * service_name, pam_handle_t **sshpam_phandle )
676
{
681
{
677
	const char *pam_user, *user = authctxt->user;
682
	const char *pam_user, *user = authctxt->user;
678
	const char **ptr_pam_user = &pam_user;
683
	const char **ptr_pam_user = &pam_user;
684
	const char *pam_service;
685
	const char **ptr_pam_service = &pam_service;
679
686
680
	if (sshpam_handle == NULL) {
687
	if (*sshpam_phandle == NULL) {
681
		if (ssh == NULL) {
688
		if (ssh == NULL && sshpam_rhost == NULL) {
682
			fatal("%s: called initially with no "
689
			fatal("%s: called initially with no "
683
			    "packet context", __func__);
690
			    "packet context", __func__);
684
		}
691
		}
685
	} if (sshpam_handle != NULL) {
692
	}
686
		/* We already have a PAM context; check if the user matches */
693
	if (*sshpam_phandle != NULL) {
687
		sshpam_err = pam_get_item(sshpam_handle,
694
		/* We already have a PAM context;
695
		 * check if the user and service name matches */
696
		sshpam_err = pam_get_item(*sshpam_phandle,
688
		    PAM_USER, (sshpam_const void **)ptr_pam_user);
697
		    PAM_USER, (sshpam_const void **)ptr_pam_user);
689
		if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0)
698
		if (sshpam_err == PAM_SUCCESS
690
			return (0);
699
		    && strcmp(user, pam_user) == 0 ) {
691
		pam_end(sshpam_handle, sshpam_err);
700
			sshpam_err = pam_get_item(*sshpam_phandle,
692
		sshpam_handle = NULL;
701
			    PAM_SERVICE, (sshpam_const void **)ptr_pam_service);
702
			if (sshpam_err == PAM_SUCCESS
703
			    && strncmp(service_name, pam_service, strlen(service_name)) == 0 ) {
704
				// full match. no reinit needed.
705
				return (0);
706
			}
707
		}
708
		/*
709
		 * Clean up previous PAM state.  No need to clean up session 
710
		 * and creds.
711
		 */
712
		if (sshpam_phandle == &sshpam_handle) {
713
			/* (This is not needed for password auth, it does not change or read these states) */
714
			sshpam_authenticated = 0;
715
			sshpam_account_status = -1;
716
		}
717
		sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, NULL);
718
		if (sshpam_err != PAM_SUCCESS)
719
		        debug3("Cannot remove PAM conv"); /* a warning only */
720
721
		pam_end(*sshpam_phandle, sshpam_err);
722
		*sshpam_phandle = NULL;
693
	}
723
	}
694
	debug("PAM: initializing for \"%s\"", user);
724
	debug("PAM: (%s) initializing for \"%s\"", service_name, user);
695
	sshpam_err =
725
	sshpam_err =
696
	    pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle);
726
	    pam_start(service_name, user, &store_conv, sshpam_phandle);
697
	sshpam_authctxt = authctxt;
727
	sshpam_authctxt = authctxt;
698
728
699
	if (sshpam_err != PAM_SUCCESS) {
729
	if (sshpam_err != PAM_SUCCESS) {
700
		pam_end(sshpam_handle, sshpam_err);
730
		pam_end(*sshpam_phandle, sshpam_err);
701
		sshpam_handle = NULL;
731
		*sshpam_phandle = NULL;
702
		return (-1);
732
		return (-1);
703
	}
733
	}
704
734
Lines 717-731 sshpam_init(struct ssh *ssh, Authctxt *authctxt) Link Here
717
	}
747
	}
718
	if (sshpam_rhost != NULL) {
748
	if (sshpam_rhost != NULL) {
719
		debug("PAM: setting PAM_RHOST to \"%s\"", sshpam_rhost);
749
		debug("PAM: setting PAM_RHOST to \"%s\"", sshpam_rhost);
720
		sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST,
750
		sshpam_err = pam_set_item(*sshpam_phandle, PAM_RHOST,
721
		    sshpam_rhost);
751
		    sshpam_rhost);
722
		if (sshpam_err != PAM_SUCCESS) {
752
		if (sshpam_err != PAM_SUCCESS) {
723
			pam_end(sshpam_handle, sshpam_err);
753
			pam_end(*sshpam_phandle, sshpam_err);
724
			sshpam_handle = NULL;
754
			*sshpam_phandle = NULL;
725
			return (-1);
755
			return (-1);
726
		}
756
		}
727
		/* Put SSH_CONNECTION in the PAM environment too */
757
		/* Put SSH_CONNECTION in the PAM environment too */
728
		pam_putenv(sshpam_handle, sshpam_conninfo);
758
		pam_putenv(*sshpam_phandle, sshpam_conninfo);
729
	}
759
	}
730
760
731
#ifdef PAM_TTY_KLUDGE
761
#ifdef PAM_TTY_KLUDGE
Lines 735-744 sshpam_init(struct ssh *ssh, Authctxt *authctxt) Link Here
735
	 * may not even set one (for tty-less connections)
765
	 * may not even set one (for tty-less connections)
736
	 */
766
	 */
737
	debug("PAM: setting PAM_TTY to \"ssh\"");
767
	debug("PAM: setting PAM_TTY to \"ssh\"");
738
	sshpam_err = pam_set_item(sshpam_handle, PAM_TTY, "ssh");
768
	sshpam_err = pam_set_item(*sshpam_phandle, PAM_TTY, "ssh");
739
	if (sshpam_err != PAM_SUCCESS) {
769
	if (sshpam_err != PAM_SUCCESS) {
740
		pam_end(sshpam_handle, sshpam_err);
770
		pam_end(*sshpam_phandle, sshpam_err);
741
		sshpam_handle = NULL;
771
		*sshpam_phandle = NULL;
742
		return (-1);
772
		return (-1);
743
	}
773
	}
744
#endif
774
#endif
Lines 771-776 sshpam_init_ctx(Authctxt *authctxt) Link Here
771
{
801
{
772
	struct pam_ctxt *ctxt;
802
	struct pam_ctxt *ctxt;
773
	int socks[2];
803
	int socks[2];
804
	char *service_name = SSHD_PAM_SERVICE;
774
805
775
	debug3("PAM: %s entering", __func__);
806
	debug3("PAM: %s entering", __func__);
776
	/*
807
	/*
Lines 780-787 sshpam_init_ctx(Authctxt *authctxt) Link Here
780
	if (!options.use_pam || sshpam_account_status == 0)
811
	if (!options.use_pam || sshpam_account_status == 0)
781
		return NULL;
812
		return NULL;
782
813
814
	if (!( options.pam_service_name == NULL || strcasecmp(options.pam_service_name, "none") == 0))
815
		service_name = options.pam_service_name;
816
783
	/* Initialize PAM */
817
	/* Initialize PAM */
784
	if (sshpam_init(NULL, authctxt) == -1) {
818
	if (sshpam_init(NULL, authctxt, service_name, &sshpam_handle) == -1) {
785
		error("PAM: initialization failed");
819
		error("PAM: initialization failed");
786
		return (NULL);
820
		return (NULL);
787
	}
821
	}
Lines 1022-1032 void Link Here
1022
start_pam(struct ssh *ssh)
1056
start_pam(struct ssh *ssh)
1023
{
1057
{
1024
	Authctxt *authctxt = (Authctxt *)ssh->authctxt;
1058
	Authctxt *authctxt = (Authctxt *)ssh->authctxt;
1059
	char *service_name = SSHD_PAM_SERVICE;
1025
1060
1026
	if (!options.use_pam)
1061
	if (!options.use_pam)
1027
		fatal("PAM: initialisation requested when UsePAM=no");
1062
		fatal("PAM: initialisation requested when UsePAM=no");
1028
1063
1029
	if (sshpam_init(ssh, authctxt) == -1)
1064
	if (!( options.pam_service_name == NULL || strcasecmp(options.pam_service_name, "none") == 0))
1065
		service_name = options.pam_service_name;
1066
1067
	if (sshpam_init(ssh, authctxt, service_name, &sshpam_handle) == -1)
1030
		fatal("PAM: initialisation failed");
1068
		fatal("PAM: initialisation failed");
1031
}
1069
}
1032
1070
Lines 1316-1325 sshpam_auth_passwd(Authctxt *authctxt, const char *password) Link Here
1316
	int flags = (options.permit_empty_passwd == 0 ?
1354
	int flags = (options.permit_empty_passwd == 0 ?
1317
	    PAM_DISALLOW_NULL_AUTHTOK : 0);
1355
	    PAM_DISALLOW_NULL_AUTHTOK : 0);
1318
	char *fake = NULL;
1356
	char *fake = NULL;
1357
	char *service_name = SSHD_PAM_SERVICE;
1319
1358
1320
	if (!options.use_pam || sshpam_handle == NULL)
1359
	if (!options.use_pam)
1321
		fatal("PAM: %s called when PAM disabled or failed to "
1360
		fatal("PAM: %s called when PAM disabled.", __func__);
1322
		    "initialise.", __func__);
1361
1362
	if (!( options.pam_service_name == NULL || strcasecmp(options.pam_service_name, "none") == 0))
1363
		service_name = options.pam_service_name;
1364
1365
	if (!( options.password_pam_service_name == NULL || strcasecmp(options.password_pam_service_name, "none") == 0))
1366
		service_name = options.password_pam_service_name;
1367
1368
	if (sshpam_init(NULL, authctxt, service_name, &sshpam_password_handle) == -1)
1369
		fatal("PAM: initialisation for password authentication failed");
1323
1370
1324
	sshpam_password = password;
1371
	sshpam_password = password;
1325
	sshpam_authctxt = authctxt;
1372
	sshpam_authctxt = authctxt;
Lines 1333-1345 sshpam_auth_passwd(Authctxt *authctxt, const char *password) Link Here
1333
	    options.permit_root_login != PERMIT_YES))
1380
	    options.permit_root_login != PERMIT_YES))
1334
		sshpam_password = fake = fake_password(password);
1381
		sshpam_password = fake = fake_password(password);
1335
1382
1336
	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
1383
	sshpam_err = pam_set_item(sshpam_password_handle, PAM_CONV,
1337
	    (const void *)&passwd_conv);
1384
	    (const void *)&passwd_conv);
1338
	if (sshpam_err != PAM_SUCCESS)
1385
	if (sshpam_err != PAM_SUCCESS)
1339
		fatal("PAM: %s: failed to set PAM_CONV: %s", __func__,
1386
		fatal("PAM: %s: failed to set PAM_CONV: %s", __func__,
1340
		    pam_strerror(sshpam_handle, sshpam_err));
1387
		    pam_strerror(sshpam_password_handle, sshpam_err));
1341
1388
1342
	sshpam_err = pam_authenticate(sshpam_handle, flags);
1389
	sshpam_err = pam_authenticate(sshpam_password_handle, flags);
1343
	sshpam_password = NULL;
1390
	sshpam_password = NULL;
1344
	free(fake);
1391
	free(fake);
1345
	if (sshpam_err == PAM_MAXTRIES)
1392
	if (sshpam_err == PAM_MAXTRIES)
Lines 1351-1357 sshpam_auth_passwd(Authctxt *authctxt, const char *password) Link Here
1351
	} else {
1398
	} else {
1352
		debug("PAM: password authentication failed for %.100s: %s",
1399
		debug("PAM: password authentication failed for %.100s: %s",
1353
		    authctxt->valid ? authctxt->user : "an illegal user",
1400
		    authctxt->valid ? authctxt->user : "an illegal user",
1354
		    pam_strerror(sshpam_handle, sshpam_err));
1401
		    pam_strerror(sshpam_password_handle, sshpam_err));
1355
		return 0;
1402
		return 0;
1356
	}
1403
	}
1357
}
1404
}
(-)a/servconf.c (+43 lines)
Lines 83-88 initialize_server_options(ServerOptions *options) Link Here
83
83
84
	/* Portable-specific options */
84
	/* Portable-specific options */
85
	options->use_pam = -1;
85
	options->use_pam = -1;
86
	options->pam_service_name = NULL;
87
	options->password_pam_service_name = NULL;
86
88
87
	/* Standard Options */
89
	/* Standard Options */
88
	options->num_ports = 0;
90
	options->num_ports = 0;
Lines 439-444 fill_default_server_options(ServerOptions *options) Link Here
439
			v = NULL; \
441
			v = NULL; \
440
		} \
442
		} \
441
	} while(0)
443
	} while(0)
444
	/* Portable-specific options */
445
	CLEAR_ON_NONE(options->pam_service_name);
446
	CLEAR_ON_NONE(options->password_pam_service_name);
447
	/* Standard Options */
442
	CLEAR_ON_NONE(options->pid_file);
448
	CLEAR_ON_NONE(options->pid_file);
443
	CLEAR_ON_NONE(options->xauth_location);
449
	CLEAR_ON_NONE(options->xauth_location);
444
	CLEAR_ON_NONE(options->banner);
450
	CLEAR_ON_NONE(options->banner);
Lines 478-483 typedef enum { Link Here
478
	sBadOption,		/* == unknown option */
484
	sBadOption,		/* == unknown option */
479
	/* Portable-specific options */
485
	/* Portable-specific options */
480
	sUsePAM,
486
	sUsePAM,
487
	sPAMServiceName,
488
	sPasswordPAMServiceName,
481
	/* Standard Options */
489
	/* Standard Options */
482
	sPort, sHostKeyFile, sLoginGraceTime,
490
	sPort, sHostKeyFile, sLoginGraceTime,
483
	sPermitRootLogin, sLogFacility, sLogLevel,
491
	sPermitRootLogin, sLogFacility, sLogLevel,
Lines 527-534 static struct { Link Here
527
	/* Portable-specific options */
535
	/* Portable-specific options */
528
#ifdef USE_PAM
536
#ifdef USE_PAM
529
	{ "usepam", sUsePAM, SSHCFG_GLOBAL },
537
	{ "usepam", sUsePAM, SSHCFG_GLOBAL },
538
	{ "pamservicename", sPAMServiceName, SSHCFG_ALL },
539
	{ "passwordpamservicename", sPasswordPAMServiceName, SSHCFG_ALL },
530
#else
540
#else
531
	{ "usepam", sUnsupported, SSHCFG_GLOBAL },
541
	{ "usepam", sUnsupported, SSHCFG_GLOBAL },
542
	{ "pamservicename", sUnsupported, SSHCFG_ALL },
543
	{ "passwordpamservicename", sUnsupported, SSHCFG_ALL },
532
#endif
544
#endif
533
	{ "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
545
	{ "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
534
	/* Standard Options */
546
	/* Standard Options */
Lines 1270-1275 process_server_config_line(ServerOptions *options, char *line, Link Here
1270
		intptr = &options->use_pam;
1282
		intptr = &options->use_pam;
1271
		goto parse_flag;
1283
		goto parse_flag;
1272
1284
1285
	case sPAMServiceName:
1286
		charptr = &options->pam_service_name;
1287
parse_string:
1288
		arg = strdelim(&cp);
1289
		if (!arg || *arg == '\0')
1290
			fatal("%s line %d: missing string argument.",
1291
			    filename, linenum);
1292
		if (*activep && *charptr == NULL) {
1293
			*charptr = xstrdup(arg);
1294
		}
1295
		break;
1296
1297
	case sPasswordPAMServiceName:
1298
		charptr = &options->password_pam_service_name;
1299
		goto parse_string;
1300
1273
	/* Standard Options */
1301
	/* Standard Options */
1274
	case sBadOption:
1302
	case sBadOption:
1275
		return -1;
1303
		return -1;
Lines 2345-2350 copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) Link Here
2345
	} \
2373
	} \
2346
} while(0)
2374
} while(0)
2347
2375
2376
	M_CP_STROPT(pam_service_name);
2377
	if (option_clear_or_none(dst->pam_service_name)) {
2378
		free(dst->pam_service_name);
2379
		dst->pam_service_name = NULL;
2380
	}
2381
	M_CP_STROPT(password_pam_service_name);
2382
	if (option_clear_or_none(dst->password_pam_service_name)) {
2383
		free(dst->password_pam_service_name);
2384
		dst->password_pam_service_name = NULL;
2385
	}
2386
2348
	/* See comment in servconf.h */
2387
	/* See comment in servconf.h */
2349
	COPY_MATCH_STRING_OPTS();
2388
	COPY_MATCH_STRING_OPTS();
2350
2389
Lines 2552-2557 dump_config(ServerOptions *o) Link Here
2552
	/* integer arguments */
2591
	/* integer arguments */
2553
#ifdef USE_PAM
2592
#ifdef USE_PAM
2554
	dump_cfg_fmtint(sUsePAM, o->use_pam);
2593
	dump_cfg_fmtint(sUsePAM, o->use_pam);
2594
	dump_cfg_string(sPAMServiceName, *o->pam_service_name == '\0'
2595
	    ? "none" : o->pam_service_name);
2596
	dump_cfg_string(sPasswordPAMServiceName, *o->password_pam_service_name == '\0'
2597
	    ? "none" : o->password_pam_service_name);
2555
#endif
2598
#endif
2556
	dump_cfg_int(sLoginGraceTime, o->login_grace_time);
2599
	dump_cfg_int(sLoginGraceTime, o->login_grace_time);
2557
	dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
2600
	dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
(-)a/servconf.h (+2 lines)
Lines 183-188 typedef struct { Link Here
183
	char   *adm_forced_command;
183
	char   *adm_forced_command;
184
184
185
	int	use_pam;		/* Enable auth via PAM */
185
	int	use_pam;		/* Enable auth via PAM */
186
	char   *pam_service_name;
187
	char   *password_pam_service_name;
186
188
187
	int	permit_tun;
189
	int	permit_tun;
188
190
(-)a/sshd_config.5 (+49 lines)
Lines 1137-1143 Available keywords are Link Here
1137
.Cm LogLevel ,
1137
.Cm LogLevel ,
1138
.Cm MaxAuthTries ,
1138
.Cm MaxAuthTries ,
1139
.Cm MaxSessions ,
1139
.Cm MaxSessions ,
1140
.Cm PAMServiceName ,
1140
.Cm PasswordAuthentication ,
1141
.Cm PasswordAuthentication ,
1142
.Cm PasswordPAMServiceName ,
1141
.Cm PermitEmptyPasswords ,
1143
.Cm PermitEmptyPasswords ,
1142
.Cm PermitListen ,
1144
.Cm PermitListen ,
1143
.Cm PermitOpen ,
1145
.Cm PermitOpen ,
Lines 1191-1200 will refuse connection attempts with a probability of rate/100 (30%) Link Here
1191
if there are currently start (10) unauthenticated connections.
1193
if there are currently start (10) unauthenticated connections.
1192
The probability increases linearly and all connection attempts
1194
The probability increases linearly and all connection attempts
1193
are refused if the number of unauthenticated connections reaches full (60).
1195
are refused if the number of unauthenticated connections reaches full (60).
1196
.It Cm PAMServiceName
1197
Specifies the service identifier to be used for pluggable authentication
1198
modules (PAM).
1199
If set to
1200
.Cm none ,
1201
the sshd executable name (usually sshd) is used.
1202
If set to
1203
.Ar name ,
1204
authentication options can be configured in a matching file in
1205
.Ar /etc/pam.d/name .
1206
The default is
1207
.Cm none .
1194
.It Cm PasswordAuthentication
1208
.It Cm PasswordAuthentication
1195
Specifies whether password authentication is allowed.
1209
Specifies whether password authentication is allowed.
1196
The default is
1210
The default is
1197
.Cm yes .
1211
.Cm yes .
1212
.It Cm PasswordPAMServiceName
1213
Specifies the service identifier to be used for pluggable authentication
1214
modules (PAM) for
1215
.Cm PasswordAuthentication
1216
only. This is only used for the authentication (auth) PAM aspect. For account and
1217
session management, as well as
1218
.Cm ChallengeResponseAuthentication ,
1219
the service name set in
1220
.Cm PAMServiceName
1221
is applied. This can be helpful to implement 2 factor authentication.
1222
Example:
1223
.Pp
1224
.Bl -item -offset indent -compact
1225
.It
1226
.Cm AuthenticationMethods
1227
.Qq publickey,keyboard-interactive password,keyboard-interactive
1228
.It
1229
.Cm PAMServiceName
1230
sshd_2factor
1231
.It
1232
.Cm PasswordPAMServiceName
1233
sshd_password
1234
.El
1235
.Pp
1236
In this example, the challenge response authentication would ask the user for
1237
the second factor, for example an OATH token, while the first factor could be
1238
either provided by ssh-key or password. This requires two different PAM
1239
configurations to be used, in this example /etc/pam.d/sshd_2factor and
1240
/etc/pam.d/sshd_password. If set to
1241
.Cm none ,
1242
the value of
1243
.Cm PAMServiceName
1244
is used.
1245
The default is
1246
.Cm none .
1198
.It Cm PermitEmptyPasswords
1247
.It Cm PermitEmptyPasswords
1199
When password authentication is allowed, it specifies whether the
1248
When password authentication is allowed, it specifies whether the
1200
server allows login to accounts with empty password strings.
1249
server allows login to accounts with empty password strings.

Return to bug 2980