ce9f02cd08
- mod_nss-bnc863518-reopen_dev_tty.diff: close(0) and open("/dev/tty", ...) to make sure that stdin can be read from. startproc may inherit wrongly opened file descriptors to httpd. (Note: An analogous fix exists in startproc(8), too.) [bnc#863518] - VirtualHost part in /etc/apache2/conf.d/mod_nss.conf is now externalized to /etc/apache2/conf.d/vhost-nss.template and not activated/read by default. [bnc#878681] - NSSCipherSuite update following additional ciphers of Feb 18 change. [bnc#878681] - mod_nss-SNI-callback.patch, mod_nss-SNI-checks.patch: server side SNI was not implemented when mod_nss was made; patches implement SNI with checks if SNI provided hostname equals Host: field in http request header. OBS-URL: https://build.opensuse.org/request/show/242385 OBS-URL: https://build.opensuse.org/package/show/mozilla:Factory/apache2-mod_nss?expand=0&rev=10
224 lines
7.2 KiB
Diff
224 lines
7.2 KiB
Diff
diff -rNU 50 ../mod_nss-1.0.8-o/nss_engine_pphrase.c ./nss_engine_pphrase.c
|
|
--- ../mod_nss-1.0.8-o/nss_engine_pphrase.c 2014-07-24 12:23:30.000000000 +0200
|
|
+++ ./nss_engine_pphrase.c 2014-07-24 13:54:23.000000000 +0200
|
|
@@ -181,199 +181,218 @@
|
|
* that may be done.
|
|
*/
|
|
static PRBool nss_check_password(unsigned char *cp)
|
|
{
|
|
int len;
|
|
unsigned char *end, ch;
|
|
|
|
len = strlen((char *)cp);
|
|
if (len < 8) {
|
|
return PR_TRUE;
|
|
}
|
|
end = cp + len;
|
|
while (cp < end) {
|
|
ch = *cp++;
|
|
if (!((ch >= 'A') && (ch <= 'Z')) &&
|
|
!((ch >= 'a') && (ch <= 'z'))) {
|
|
/* pass phrase has at least one non alphabetic in it */
|
|
return PR_TRUE;
|
|
}
|
|
}
|
|
return PR_TRUE;
|
|
}
|
|
|
|
/*
|
|
* Password callback so the user is not prompted to enter the password
|
|
* after the server starts.
|
|
*/
|
|
static char * nss_no_password(PK11SlotInfo *slot, PRBool retry, void *arg)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Password callback to prompt the user for a password. This requires
|
|
* twiddling with the tty. Alternatively, if the file password.conf
|
|
* exists then it may be used to store the token password(s).
|
|
*/
|
|
static char *nss_get_password(FILE *input, FILE *output,
|
|
PK11SlotInfo *slot,
|
|
PRBool (*ok)(unsigned char *),
|
|
pphrase_arg_t *parg)
|
|
{
|
|
char *pwdstr = NULL;
|
|
char *token_name = NULL;
|
|
int tmp;
|
|
FILE *pwd_fileptr;
|
|
char *ptr;
|
|
char line[1024];
|
|
unsigned char phrase[200];
|
|
int infd = fileno(input);
|
|
+ int tmpfd;
|
|
int isTTY = isatty(infd);
|
|
|
|
token_name = PK11_GetTokenName(slot);
|
|
|
|
if (parg->mc->pphrase_dialog_type == SSL_PPTYPE_FILE ||
|
|
parg->mc->pphrase_dialog_type == SSL_PPTYPE_DEFER) {
|
|
/* Try to get the passwords from the password file if it exists.
|
|
* THIS IS UNSAFE and is provided for convenience only. Without this
|
|
* capability the server would have to be started in foreground mode.
|
|
*/
|
|
if ((*parg->mc->pphrase_dialog_path != '\0') &&
|
|
((pwd_fileptr = fopen(parg->mc->pphrase_dialog_path, "r")) != NULL)) {
|
|
while(fgets(line, 1024, pwd_fileptr)) {
|
|
if (PL_strstr(line, token_name) == line) {
|
|
tmp = PL_strlen(line) - 1;
|
|
while((line[tmp] == ' ') || (line[tmp] == '\n'))
|
|
tmp--;
|
|
line[tmp+1] = '\0';
|
|
ptr = PL_strchr(line, ':');
|
|
if (ptr == NULL) {
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
|
|
"Malformed password entry for token %s. Format should be token:password", token_name);
|
|
continue;
|
|
}
|
|
for(tmp=1; ptr[tmp] == ' '; tmp++) {}
|
|
pwdstr = strdup(&(ptr[tmp]));
|
|
}
|
|
}
|
|
fclose(pwd_fileptr);
|
|
} else {
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
|
|
"Unable to open password file %s", parg->mc->pphrase_dialog_path);
|
|
nss_die();
|
|
}
|
|
}
|
|
|
|
/* For SSL_PPTYPE_DEFER we only want to authenticate passwords found
|
|
* in the password file.
|
|
*/
|
|
if ((parg->mc->pphrase_dialog_type == SSL_PPTYPE_DEFER) &&
|
|
(pwdstr == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
/* This purposely comes after the file check because that is more
|
|
* authoritative.
|
|
*/
|
|
if (parg->mc->nInitCount > 1) {
|
|
char buf[1024];
|
|
apr_status_t rv;
|
|
apr_size_t nBytes = 1024;
|
|
struct sembuf sb;
|
|
|
|
/* lock the pipe */
|
|
sb.sem_num = 0;
|
|
sb.sem_op = -1;
|
|
sb.sem_flg = SEM_UNDO;
|
|
if (semop(parg->mc->semid, &sb, 1) == -1) {
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
|
|
"Unable to reserve semaphore resource");
|
|
}
|
|
|
|
snprintf(buf, 1024, "RETR\t%s", token_name);
|
|
rv = apr_file_write_full(parg->mc->proc.in, buf, strlen(buf), NULL);
|
|
if (rv != APR_SUCCESS) {
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
|
|
"Unable to write to pin store for slot: %s APR err: %d", PK11_GetTokenName(slot), rv);
|
|
nss_die();
|
|
}
|
|
|
|
/* The helper just returns a token pw or "", so we don't have much
|
|
* to check for.
|
|
*/
|
|
memset(buf, 0, sizeof(buf));
|
|
rv = apr_file_read(parg->mc->proc.out, buf, &nBytes);
|
|
sb.sem_op = 1;
|
|
if (semop(parg->mc->semid, &sb, 1) == -1) {
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
|
|
"Unable to free semaphore resource");
|
|
/* perror("semop free resource id"); */
|
|
}
|
|
|
|
if (rv != APR_SUCCESS) {
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
|
|
"Unable to read from pin store for slot: %s APR err: %d", PK11_GetTokenName(slot), rv);
|
|
nss_die();
|
|
}
|
|
|
|
/* Just return what we got. If we got this far and we don't have a
|
|
* PIN then I/O is already shut down, so we can't do anything really
|
|
* clever.
|
|
*/
|
|
pwdstr = strdup(buf);
|
|
}
|
|
|
|
/* If we got a password we're done */
|
|
if (pwdstr)
|
|
return pwdstr;
|
|
-
|
|
+
|
|
+ /* It happens that stdin is not opened with O_RDONLY. Better make sure
|
|
+ * it is and re-open /dev/tty.
|
|
+ */
|
|
+ close(infd); /* is 0 normally. open(2) will return first available. */
|
|
+ tmpfd = open("/dev/tty", O_RDONLY);
|
|
+ if( tmpfd == -1) {
|
|
+ fprintf(output, "Cannot open /dev/tty for reading the passphrase.\n");
|
|
+ nss_die();
|
|
+ }
|
|
+ if(tmpfd != infd) {
|
|
+ if( dup2(tmpfd, infd) != infd) {
|
|
+ fprintf(output, "Problem duplicating /dev/tty file descriptor.\n");
|
|
+ close(tmpfd);
|
|
+ nss_die();
|
|
+ }
|
|
+ close(tmpfd);
|
|
+ }
|
|
+
|
|
for (;;) {
|
|
/* Prompt for password */
|
|
if (isTTY) {
|
|
if (parg->retryCount > 0) {
|
|
fprintf(output, "Password incorrect. Please try again.\n");
|
|
}
|
|
fprintf(output, "%s", prompt);
|
|
echoOff(infd);
|
|
}
|
|
fgets((char*) phrase, sizeof(phrase), input);
|
|
if (isTTY) {
|
|
fprintf(output, "\n");
|
|
echoOn(infd);
|
|
}
|
|
/* stomp on newline */
|
|
phrase[strlen((char*)phrase)-1] = 0;
|
|
|
|
/* Validate password */
|
|
if (!(*ok)(phrase)) {
|
|
/* Not weird enough */
|
|
if (!isTTY) return 0;
|
|
fprintf(output, "Password must be at least 8 characters long with one or more\n");
|
|
fprintf(output, "non-alphabetic characters\n");
|
|
continue;
|
|
}
|
|
if (PK11_IsFIPS() && strlen(phrase) == 0) {
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
|
|
"The FIPS security policy requires that a password be set.");
|
|
nss_die();
|
|
} else
|
|
return (char*) PORT_Strdup((char*)phrase);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Turn the echoing off on a tty.
|
|
*/
|
|
static void echoOff(int fd)
|
|
{
|
|
if (isatty(fd)) {
|
|
struct termios tio;
|
|
tcgetattr(fd, &tio);
|
|
tio.c_lflag &= ~ECHO;
|
|
tcsetattr(fd, TCSAFLUSH, &tio);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Turn the echoing on on a tty.
|
|
*/
|