|
|
4418f4 |
/*
|
|
|
4418f4 |
Copyright 2005 Red Hat, Inc.
|
|
|
4418f4 |
|
|
|
4418f4 |
This program is free software; you can redistribute it and/or modify
|
|
|
4418f4 |
it under the terms of the GNU General Public License as published by
|
|
|
4418f4 |
the Free Software Foundation; either version 2 of the License, or
|
|
|
4418f4 |
(at your option) any later version.
|
|
|
4418f4 |
|
|
|
4418f4 |
This program is distributed in the hope that it will be useful,
|
|
|
4418f4 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
4418f4 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
4418f4 |
GNU General Public License for more details.
|
|
|
4418f4 |
|
|
|
4418f4 |
You should have received a copy of the GNU General Public License
|
|
|
4418f4 |
along with this program; if not, write to the Free Software
|
|
|
4418f4 |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
4418f4 |
|
|
|
4418f4 |
In addition, as a special exception, Red Hat, Inc. gives permission
|
|
|
4418f4 |
to link the code of this program with the OpenSSL library (or with
|
|
|
4418f4 |
modified versions of OpenSSL that use the same license as OpenSSL),
|
|
|
4418f4 |
and distribute linked combinations including the two. You must obey
|
|
|
4418f4 |
the GNU General Public License in all respects for all of the code
|
|
|
4418f4 |
used other than OpenSSL. If you modify this file, you may extend
|
|
|
4418f4 |
this exception to your version of the file, but you are not
|
|
|
4418f4 |
obligated to do so. If you do not wish to do so, delete this
|
|
|
4418f4 |
exception statement from your version.
|
|
|
4418f4 |
|
|
|
4418f4 |
*/
|
|
|
4418f4 |
|
|
|
4418f4 |
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
4418f4 |
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
4418f4 |
*
|
|
|
4418f4 |
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
4418f4 |
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
4418f4 |
* the License. You may obtain a copy of the License at
|
|
|
4418f4 |
* http://www.mozilla.org/MPL/
|
|
|
4418f4 |
*
|
|
|
4418f4 |
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
4418f4 |
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
4418f4 |
* for the specific language governing rights and limitations under the
|
|
|
4418f4 |
* License.
|
|
|
4418f4 |
*
|
|
|
4418f4 |
* The Original Code is the Netscape security libraries.
|
|
|
4418f4 |
*
|
|
|
4418f4 |
* The Initial Developer of the Original Code is
|
|
|
4418f4 |
* Netscape Communications Corporation.
|
|
|
4418f4 |
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
|
|
4418f4 |
* the Initial Developer. All Rights Reserved.
|
|
|
4418f4 |
*
|
|
|
4418f4 |
* Contributor(s):
|
|
|
4418f4 |
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
|
|
4418f4 |
*
|
|
|
4418f4 |
* Alternatively, the contents of this file may be used under the terms of
|
|
|
4418f4 |
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
4418f4 |
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
4418f4 |
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
4418f4 |
* of those above. If you wish to allow use of your version of this file only
|
|
|
4418f4 |
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
4418f4 |
* use your version of this file under the terms of the MPL, indicate your
|
|
|
4418f4 |
* decision by deleting the provisions above and replace them with the notice
|
|
|
4418f4 |
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
4418f4 |
* the provisions above, a recipient may use your version of this file under
|
|
|
4418f4 |
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
4418f4 |
*
|
|
|
4418f4 |
* ***** END LICENSE BLOCK ***** */
|
|
|
4418f4 |
/*
|
|
|
4418f4 |
** secutil.c - various functions used by security stuff
|
|
|
4418f4 |
**
|
|
|
4418f4 |
** This code comes from the NSS internal library used by the
|
|
|
4418f4 |
** the NSS security tools.
|
|
|
4418f4 |
**
|
|
|
4418f4 |
*/
|
|
|
4418f4 |
|
|
|
4418f4 |
#include <prtypes.h>
|
|
|
4418f4 |
#include <prtime.h>
|
|
|
4418f4 |
#include <prlong.h>
|
|
|
4418f4 |
#include <prerror.h>
|
|
|
4418f4 |
#include <prprf.h>
|
|
|
4418f4 |
#include <plgetopt.h>
|
|
|
4418f4 |
#include <prenv.h>
|
|
|
4418f4 |
#include <prnetdb.h>
|
|
|
4418f4 |
|
|
|
4418f4 |
#include <cryptohi.h>
|
|
|
4418f4 |
#include <secpkcs7.h>
|
|
|
4418f4 |
#include <secpkcs5.h>
|
|
|
4418f4 |
#include <stdarg.h>
|
|
|
4418f4 |
|
|
|
4418f4 |
#include <sys/stat.h>
|
|
|
4418f4 |
#include <errno.h>
|
|
|
4418f4 |
|
|
|
4418f4 |
#include <unistd.h>
|
|
|
4418f4 |
|
|
|
4418f4 |
/* for SEC_TraverseNames */
|
|
|
4418f4 |
#include <cert.h>
|
|
|
4418f4 |
#include <certt.h>
|
|
|
4418f4 |
#include <certdb.h>
|
|
|
4418f4 |
|
|
|
4418f4 |
#include <secmod.h>
|
|
|
4418f4 |
#include <pk11func.h>
|
|
|
4418f4 |
#include <secoid.h>
|
|
|
4418f4 |
|
|
|
4418f4 |
#include "secutil.h"
|
|
|
4418f4 |
|
|
|
4418f4 |
#if(0)
|
|
|
4418f4 |
static char consoleName[] = {
|
|
|
4418f4 |
"/dev/tty"
|
|
|
4418f4 |
};
|
|
|
4418f4 |
#endif
|
|
|
4418f4 |
|
|
|
4418f4 |
char *
|
|
|
4418f4 |
SECU_GetString(int16 error_number)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
|
|
|
4418f4 |
static char errString[80];
|
|
|
4418f4 |
sprintf(errString, "Unknown error string (%d)", error_number);
|
|
|
4418f4 |
return errString;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
static void
|
|
|
4418f4 |
SECU_PrintErrMsg(FILE *out, int level, char *progName, char *msg, va_list args)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
PRErrorCode err = PORT_GetError();
|
|
|
4418f4 |
const char * errString = PORT_ErrorToString(err);
|
|
|
4418f4 |
|
|
|
4418f4 |
SECU_Indent(out, level);
|
|
|
4418f4 |
fprintf(out, "%s: ", progName);
|
|
|
4418f4 |
vfprintf(out, msg, args);
|
|
|
4418f4 |
if (errString != NULL && PORT_Strlen(errString) > 0)
|
|
|
4418f4 |
fprintf(out, ": %s\n", errString);
|
|
|
4418f4 |
else
|
|
|
4418f4 |
fprintf(out, ": error %d\n", (int)err);
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
void SECU_PrintError(char *progName, char *msg, ...)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
va_list args;
|
|
|
4418f4 |
|
|
|
4418f4 |
va_start(args, msg);
|
|
|
4418f4 |
SECU_PrintErrMsg(stderr, 0, progName, msg, args);
|
|
|
4418f4 |
va_end(args);
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
#define INDENT_MULT 4
|
|
|
4418f4 |
void
|
|
|
4418f4 |
SECU_Indent(FILE *out, int level)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
int i;
|
|
|
4418f4 |
|
|
|
4418f4 |
for (i = 0; i < level; i++) {
|
|
|
4418f4 |
fprintf(out, " ");
|
|
|
4418f4 |
}
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
static void secu_Newline(FILE *out)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
fprintf(out, "\n");
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
void
|
|
|
4418f4 |
SECU_PrintAsHex(FILE *out, SECItem *data, const char *m, int level)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
unsigned i;
|
|
|
4418f4 |
int column;
|
|
|
4418f4 |
PRBool isString = PR_TRUE;
|
|
|
4418f4 |
PRBool isWhiteSpace = PR_TRUE;
|
|
|
4418f4 |
PRBool printedHex = PR_FALSE;
|
|
|
4418f4 |
unsigned int limit = 15;
|
|
|
4418f4 |
|
|
|
4418f4 |
if ( m ) {
|
|
|
4418f4 |
SECU_Indent(out, level); fprintf(out, "%s:\n", m);
|
|
|
4418f4 |
level++;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
SECU_Indent(out, level); column = level*INDENT_MULT;
|
|
|
4418f4 |
if (!data->len) {
|
|
|
4418f4 |
fprintf(out, "(empty)\n");
|
|
|
4418f4 |
return;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
/* take a pass to see if it's all printable. */
|
|
|
4418f4 |
for (i = 0; i < data->len; i++) {
|
|
|
4418f4 |
unsigned char val = data->data[i];
|
|
|
4418f4 |
if (!val || !isprint(val)) {
|
|
|
4418f4 |
isString = PR_FALSE;
|
|
|
4418f4 |
break;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
if (isWhiteSpace && !isspace(val)) {
|
|
|
4418f4 |
isWhiteSpace = PR_FALSE;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
/* Short values, such as bit strings (which are printed with this
|
|
|
4418f4 |
** function) often look like strings, but we want to see the bits.
|
|
|
4418f4 |
** so this test assures that short values will be printed in hex,
|
|
|
4418f4 |
** perhaps in addition to being printed as strings.
|
|
|
4418f4 |
** The threshold size (4 bytes) is arbitrary.
|
|
|
4418f4 |
*/
|
|
|
4418f4 |
if (!isString || data->len <= 4) {
|
|
|
4418f4 |
for (i = 0; i < data->len; i++) {
|
|
|
4418f4 |
if (i != data->len - 1) {
|
|
|
4418f4 |
fprintf(out, "%02x:", data->data[i]);
|
|
|
4418f4 |
column += 3;
|
|
|
4418f4 |
} else {
|
|
|
4418f4 |
fprintf(out, "%02x", data->data[i]);
|
|
|
4418f4 |
column += 2;
|
|
|
4418f4 |
break;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
if (column > 76 || (i % 16 == limit)) {
|
|
|
4418f4 |
secu_Newline(out);
|
|
|
4418f4 |
SECU_Indent(out, level);
|
|
|
4418f4 |
column = level*INDENT_MULT;
|
|
|
4418f4 |
limit = i % 16;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
}
|
|
|
4418f4 |
printedHex = PR_TRUE;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
if (isString && !isWhiteSpace) {
|
|
|
4418f4 |
if (printedHex != PR_FALSE) {
|
|
|
4418f4 |
secu_Newline(out);
|
|
|
4418f4 |
SECU_Indent(out, level); column = level*INDENT_MULT;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
for (i = 0; i < data->len; i++) {
|
|
|
4418f4 |
unsigned char val = data->data[i];
|
|
|
4418f4 |
|
|
|
4418f4 |
if (val) {
|
|
|
4418f4 |
fprintf(out,"%c",val);
|
|
|
4418f4 |
column++;
|
|
|
4418f4 |
} else {
|
|
|
4418f4 |
column = 77;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
if (column > 76) {
|
|
|
4418f4 |
secu_Newline(out);
|
|
|
4418f4 |
SECU_Indent(out, level); column = level*INDENT_MULT;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
}
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
if (column != level*INDENT_MULT) {
|
|
|
4418f4 |
secu_Newline(out);
|
|
|
4418f4 |
}
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
/* This function does NOT expect a DER type and length. */
|
|
|
4418f4 |
SECOidTag
|
|
|
4418f4 |
SECU_PrintObjectID(FILE *out, SECItem *oid, char *m, int level)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
SECOidData *oiddata;
|
|
|
4418f4 |
char *oidString = NULL;
|
|
|
4418f4 |
|
|
|
4418f4 |
oiddata = SECOID_FindOID(oid);
|
|
|
4418f4 |
if (oiddata != NULL) {
|
|
|
4418f4 |
const char *name = oiddata->desc;
|
|
|
4418f4 |
SECU_Indent(out, level);
|
|
|
4418f4 |
if (m != NULL)
|
|
|
4418f4 |
fprintf(out, "%s: ", m);
|
|
|
4418f4 |
fprintf(out, "%s\n", name);
|
|
|
4418f4 |
return oiddata->offset;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
oidString = CERT_GetOidString(oid);
|
|
|
4418f4 |
if (oidString) {
|
|
|
4418f4 |
SECU_Indent(out, level);
|
|
|
4418f4 |
if (m != NULL)
|
|
|
4418f4 |
fprintf(out, "%s: ", m);
|
|
|
4418f4 |
fprintf(out, "%s\n", oidString);
|
|
|
4418f4 |
PR_smprintf_free(oidString);
|
|
|
4418f4 |
return SEC_OID_UNKNOWN;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
SECU_PrintAsHex(out, oid, m, level);
|
|
|
4418f4 |
return SEC_OID_UNKNOWN;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
void
|
|
|
4418f4 |
SECU_PrintSystemError(char *progName, char *msg, ...)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
va_list args;
|
|
|
4418f4 |
|
|
|
4418f4 |
va_start(args, msg);
|
|
|
4418f4 |
fprintf(stderr, "%s: ", progName);
|
|
|
4418f4 |
vfprintf(stderr, msg, args);
|
|
|
4418f4 |
fprintf(stderr, ": %s\n", strerror(errno));
|
|
|
4418f4 |
va_end(args);
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
#if(0)
|
|
|
4418f4 |
static void
|
|
|
4418f4 |
secu_ClearPassword(char *p)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
if (p) {
|
|
|
4418f4 |
PORT_Memset(p, 0, PORT_Strlen(p));
|
|
|
4418f4 |
PORT_Free(p);
|
|
|
4418f4 |
}
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
char *
|
|
|
4418f4 |
SECU_GetPasswordString(void *arg, char *prompt)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
char *p = NULL;
|
|
|
4418f4 |
FILE *input, *output;
|
|
|
4418f4 |
|
|
|
4418f4 |
/* open terminal */
|
|
|
4418f4 |
input = fopen(consoleName, "r");
|
|
|
4418f4 |
if (input == NULL) {
|
|
|
4418f4 |
fprintf(stderr, "Error opening input terminal for read\n");
|
|
|
4418f4 |
return NULL;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
output = fopen(consoleName, "w");
|
|
|
4418f4 |
if (output == NULL) {
|
|
|
4418f4 |
fprintf(stderr, "Error opening output terminal for write\n");
|
|
|
4418f4 |
return NULL;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
p = SEC_GetPassword (input, output, prompt, SEC_BlindCheckPassword);
|
|
|
4418f4 |
|
|
|
4418f4 |
fclose(input);
|
|
|
4418f4 |
fclose(output);
|
|
|
4418f4 |
|
|
|
4418f4 |
return p;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
#endif
|
|
|
4418f4 |
|
|
|
4418f4 |
|
|
|
4418f4 |
/*
|
|
|
4418f4 |
* p a s s w o r d _ h a r d c o d e
|
|
|
4418f4 |
*
|
|
|
4418f4 |
* A function to use the password passed in the -f(pwfile) argument
|
|
|
4418f4 |
* of the command line.
|
|
|
4418f4 |
* After use once, null it out otherwise PKCS11 calls us forever.?
|
|
|
4418f4 |
*
|
|
|
4418f4 |
*/
|
|
|
4418f4 |
char *
|
|
|
4418f4 |
SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
char* phrases, *phrase;
|
|
|
4418f4 |
PRFileDesc *fd;
|
|
|
4418f4 |
PRInt32 nb;
|
|
|
4418f4 |
const char *pwFile = (const char *)arg;
|
|
|
4418f4 |
int i;
|
|
|
4418f4 |
const long maxPwdFileSize = 4096;
|
|
|
4418f4 |
char* tokenName = NULL;
|
|
|
4418f4 |
int tokenLen = 0;
|
|
|
4418f4 |
|
|
|
4418f4 |
if (!pwFile) {
|
|
|
4418f4 |
return 0;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
if (retry) {
|
|
|
4418f4 |
return 0; /* no good retrying - the files contents will be the same */
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
phrases = PORT_ZAlloc(maxPwdFileSize);
|
|
|
4418f4 |
|
|
|
4418f4 |
if (!phrases) {
|
|
|
4418f4 |
return 0; /* out of memory */
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
fd = PR_Open(pwFile, PR_RDONLY, 0);
|
|
|
4418f4 |
if (!fd) {
|
|
|
4418f4 |
fprintf(stderr, "No password file \"%s\" exists.\n", pwFile);
|
|
|
4418f4 |
PORT_Free(phrases);
|
|
|
4418f4 |
return NULL;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
nb = PR_Read(fd, phrases, maxPwdFileSize);
|
|
|
4418f4 |
|
|
|
4418f4 |
PR_Close(fd);
|
|
|
4418f4 |
|
|
|
4418f4 |
if (nb == 0) {
|
|
|
4418f4 |
fprintf(stderr,"password file contains no data\n");
|
|
|
4418f4 |
PORT_Free(phrases);
|
|
|
4418f4 |
return NULL;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
if (slot) {
|
|
|
4418f4 |
tokenName = PK11_GetTokenName(slot);
|
|
|
4418f4 |
if (tokenName) {
|
|
|
4418f4 |
tokenLen = PORT_Strlen(tokenName);
|
|
|
4418f4 |
}
|
|
|
4418f4 |
}
|
|
|
4418f4 |
i = 0;
|
|
|
4418f4 |
do {
|
|
|
4418f4 |
int startphrase = i;
|
|
|
4418f4 |
int phraseLen;
|
|
|
4418f4 |
|
|
|
4418f4 |
/* handle the Windows EOL case */
|
|
|
4418f4 |
while (phrases[i] != '\r' && phrases[i] != '\n' && i < nb) i++;
|
|
|
4418f4 |
/* terminate passphrase */
|
|
|
4418f4 |
phrases[i++] = '\0';
|
|
|
4418f4 |
/* clean up any EOL before the start of the next passphrase */
|
|
|
4418f4 |
while ( (i
|
|
|
4418f4 |
phrases[i++] = '\0';
|
|
|
4418f4 |
}
|
|
|
4418f4 |
/* now analyze the current passphrase */
|
|
|
4418f4 |
phrase = &phrases[startphrase];
|
|
|
4418f4 |
if (!tokenName)
|
|
|
4418f4 |
break;
|
|
|
4418f4 |
if (PORT_Strncmp(phrase, tokenName, tokenLen)) continue;
|
|
|
4418f4 |
phraseLen = PORT_Strlen(phrase);
|
|
|
4418f4 |
if (phraseLen < (tokenLen+1)) continue;
|
|
|
4418f4 |
if (phrase[tokenLen] != ':') continue;
|
|
|
4418f4 |
phrase = &phrase[tokenLen+1];
|
|
|
4418f4 |
break;
|
|
|
4418f4 |
|
|
|
4418f4 |
} while (i
|
|
|
4418f4 |
|
|
|
4418f4 |
phrase = PORT_Strdup((char*)phrase);
|
|
|
4418f4 |
PORT_Free(phrases);
|
|
|
4418f4 |
return phrase;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
char *
|
|
|
4418f4 |
SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
#if(0)
|
|
|
4418f4 |
char prompt[255];
|
|
|
4418f4 |
#endif
|
|
|
4418f4 |
secuPWData *pwdata = (secuPWData *)arg;
|
|
|
4418f4 |
secuPWData pwnull = { PW_NONE, 0 };
|
|
|
4418f4 |
secuPWData pwxtrn = { PW_EXTERNAL, "external" };
|
|
|
4418f4 |
char *pw;
|
|
|
4418f4 |
|
|
|
4418f4 |
if (pwdata == NULL)
|
|
|
4418f4 |
pwdata = &pwnull;
|
|
|
4418f4 |
|
|
|
4418f4 |
if (PK11_ProtectedAuthenticationPath(slot)) {
|
|
|
4418f4 |
pwdata = &pwxtrn;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
if (retry && pwdata->source != PW_NONE) {
|
|
|
4418f4 |
PR_fprintf(PR_STDERR, "Incorrect password/PIN entered.\n");
|
|
|
4418f4 |
return NULL;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
switch (pwdata->source) {
|
|
|
4418f4 |
#if(0)
|
|
|
4418f4 |
case PW_NONE:
|
|
|
4418f4 |
sprintf(prompt, "Enter Password or Pin for \"%s\":",
|
|
|
4418f4 |
PK11_GetTokenName(slot));
|
|
|
4418f4 |
return SECU_GetPasswordString(NULL, prompt);
|
|
|
4418f4 |
#endif
|
|
|
4418f4 |
|
|
|
4418f4 |
case PW_FROMFILE:
|
|
|
4418f4 |
/* Instead of opening and closing the file every time, get the pw
|
|
|
4418f4 |
* once, then keep it in memory (duh).
|
|
|
4418f4 |
*/
|
|
|
4418f4 |
pw = SECU_FilePasswd(slot, retry, pwdata->data);
|
|
|
4418f4 |
pwdata->source = PW_PLAINTEXT;
|
|
|
4418f4 |
pwdata->data = PL_strdup(pw);
|
|
|
4418f4 |
/* it's already been dup'ed */
|
|
|
4418f4 |
return pw;
|
|
|
4418f4 |
#if(0)
|
|
|
4418f4 |
case PW_EXTERNAL:
|
|
|
4418f4 |
sprintf(prompt,
|
|
|
4418f4 |
"Press Enter, then enter PIN for \"%s\" on external device.\n",
|
|
|
4418f4 |
PK11_GetTokenName(slot));
|
|
|
4418f4 |
(void) SECU_GetPasswordString(NULL, prompt);
|
|
|
4418f4 |
/* Fall Through */
|
|
|
4418f4 |
#endif
|
|
|
4418f4 |
case PW_PLAINTEXT:
|
|
|
4418f4 |
return PL_strdup(pwdata->data);
|
|
|
4418f4 |
default:
|
|
|
4418f4 |
break;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
PR_fprintf(PR_STDERR, "Password check failed: No password found.\n");
|
|
|
4418f4 |
return NULL;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
/*
|
|
|
4418f4 |
* Password callback so the user is not prompted to enter the password
|
|
|
4418f4 |
* after the server starts.
|
|
|
4418f4 |
*/
|
|
|
4418f4 |
char *SECU_NoPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
return NULL;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
SECStatus
|
|
|
4418f4 |
secu_StdinToItem(SECItem *dst)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
unsigned char buf[1000];
|
|
|
4418f4 |
PRInt32 numBytes;
|
|
|
4418f4 |
PRBool notDone = PR_TRUE;
|
|
|
4418f4 |
|
|
|
4418f4 |
dst->len = 0;
|
|
|
4418f4 |
dst->data = NULL;
|
|
|
4418f4 |
|
|
|
4418f4 |
while (notDone) {
|
|
|
4418f4 |
numBytes = PR_Read(PR_STDIN, buf, sizeof(buf));
|
|
|
4418f4 |
|
|
|
4418f4 |
if (numBytes < 0) {
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
if (numBytes == 0)
|
|
|
4418f4 |
break;
|
|
|
4418f4 |
|
|
|
4418f4 |
if (dst->data) {
|
|
|
4418f4 |
unsigned char * p = dst->data;
|
|
|
4418f4 |
dst->data = (unsigned char*)PORT_Realloc(p, dst->len + numBytes);
|
|
|
4418f4 |
if (!dst->data) {
|
|
|
4418f4 |
PORT_Free(p);
|
|
|
4418f4 |
}
|
|
|
4418f4 |
} else {
|
|
|
4418f4 |
dst->data = (unsigned char*)PORT_Alloc(numBytes);
|
|
|
4418f4 |
}
|
|
|
4418f4 |
if (!dst->data) {
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
PORT_Memcpy(dst->data + dst->len, buf, numBytes);
|
|
|
4418f4 |
dst->len += numBytes;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
return SECSuccess;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
SECStatus
|
|
|
4418f4 |
SECU_FileToItem(SECItem *dst, PRFileDesc *src)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
PRFileInfo info;
|
|
|
4418f4 |
PRInt32 numBytes;
|
|
|
4418f4 |
PRStatus prStatus;
|
|
|
4418f4 |
|
|
|
4418f4 |
if (src == PR_STDIN)
|
|
|
4418f4 |
return secu_StdinToItem(dst);
|
|
|
4418f4 |
|
|
|
4418f4 |
prStatus = PR_GetOpenFileInfo(src, &info;;
|
|
|
4418f4 |
|
|
|
4418f4 |
if (prStatus != PR_SUCCESS) {
|
|
|
4418f4 |
PORT_SetError(SEC_ERROR_IO);
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
/* XXX workaround for 3.1, not all utils zero dst before sending */
|
|
|
4418f4 |
dst->data = 0;
|
|
|
4418f4 |
if (!SECITEM_AllocItem(NULL, dst, info.size))
|
|
|
4418f4 |
goto loser;
|
|
|
4418f4 |
|
|
|
4418f4 |
numBytes = PR_Read(src, dst->data, info.size);
|
|
|
4418f4 |
if (numBytes != info.size) {
|
|
|
4418f4 |
PORT_SetError(SEC_ERROR_IO);
|
|
|
4418f4 |
goto loser;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
return SECSuccess;
|
|
|
4418f4 |
loser:
|
|
|
4418f4 |
SECITEM_FreeItem(dst, PR_FALSE);
|
|
|
4418f4 |
dst->data = NULL;
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
SECStatus
|
|
|
4418f4 |
SECU_TextFileToItem(SECItem *dst, PRFileDesc *src)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
PRFileInfo info;
|
|
|
4418f4 |
PRInt32 numBytes;
|
|
|
4418f4 |
PRStatus prStatus;
|
|
|
4418f4 |
unsigned char *buf;
|
|
|
4418f4 |
|
|
|
4418f4 |
if (src == PR_STDIN)
|
|
|
4418f4 |
return secu_StdinToItem(dst);
|
|
|
4418f4 |
|
|
|
4418f4 |
prStatus = PR_GetOpenFileInfo(src, &info;;
|
|
|
4418f4 |
|
|
|
4418f4 |
if (prStatus != PR_SUCCESS) {
|
|
|
4418f4 |
PORT_SetError(SEC_ERROR_IO);
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
buf = (unsigned char*)PORT_Alloc(info.size);
|
|
|
4418f4 |
if (!buf)
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
|
|
|
4418f4 |
numBytes = PR_Read(src, buf, info.size);
|
|
|
4418f4 |
if (numBytes != info.size) {
|
|
|
4418f4 |
PORT_SetError(SEC_ERROR_IO);
|
|
|
4418f4 |
goto loser;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
if (buf[numBytes-1] == '\n') numBytes--;
|
|
|
4418f4 |
#ifdef _WINDOWS
|
|
|
4418f4 |
if (buf[numBytes-1] == '\r') numBytes--;
|
|
|
4418f4 |
#endif
|
|
|
4418f4 |
|
|
|
4418f4 |
/* XXX workaround for 3.1, not all utils zero dst before sending */
|
|
|
4418f4 |
dst->data = 0;
|
|
|
4418f4 |
if (!SECITEM_AllocItem(NULL, dst, numBytes))
|
|
|
4418f4 |
goto loser;
|
|
|
4418f4 |
|
|
|
4418f4 |
memcpy(dst->data, buf, numBytes);
|
|
|
4418f4 |
|
|
|
4418f4 |
PORT_Free(buf);
|
|
|
4418f4 |
return SECSuccess;
|
|
|
4418f4 |
loser:
|
|
|
4418f4 |
PORT_Free(buf);
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
SECStatus
|
|
|
4418f4 |
SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
SECStatus rv;
|
|
|
4418f4 |
if (ascii) {
|
|
|
4418f4 |
/* First convert ascii to binary */
|
|
|
4418f4 |
SECItem filedata;
|
|
|
4418f4 |
char *asc, *body;
|
|
|
4418f4 |
|
|
|
4418f4 |
/* Read in ascii data */
|
|
|
4418f4 |
rv = SECU_FileToItem(&filedata, inFile);
|
|
|
4418f4 |
asc = (char *)filedata.data;
|
|
|
4418f4 |
if (!asc) {
|
|
|
4418f4 |
fprintf(stderr, "unable to read data from input file\n");
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
/* check for headers and trailers and remove them */
|
|
|
4418f4 |
if ((body = strstr(asc, "-----BEGIN")) != NULL) {
|
|
|
4418f4 |
char *trailer = NULL;
|
|
|
4418f4 |
asc = body;
|
|
|
4418f4 |
body = PORT_Strchr(body, '\n');
|
|
|
4418f4 |
if (!body)
|
|
|
4418f4 |
body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */
|
|
|
4418f4 |
if (body)
|
|
|
4418f4 |
trailer = strstr(++body, "-----END");
|
|
|
4418f4 |
if (trailer != NULL) {
|
|
|
4418f4 |
*trailer = '\0';
|
|
|
4418f4 |
} else {
|
|
|
4418f4 |
fprintf(stderr, "input has header but no trailer\n");
|
|
|
4418f4 |
PORT_Free(filedata.data);
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
} else {
|
|
|
4418f4 |
body = asc;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
/* Convert to binary */
|
|
|
4418f4 |
rv = ATOB_ConvertAsciiToItem(der, body);
|
|
|
4418f4 |
if (rv) {
|
|
|
4418f4 |
fprintf(stderr, "error converting ascii to binary (%d)\n",
|
|
|
4418f4 |
PORT_GetError());
|
|
|
4418f4 |
PORT_Free(filedata.data);
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
PORT_Free(filedata.data);
|
|
|
4418f4 |
} else {
|
|
|
4418f4 |
/* Read in binary der */
|
|
|
4418f4 |
rv = SECU_FileToItem(der, inFile);
|
|
|
4418f4 |
if (rv) {
|
|
|
4418f4 |
fprintf(stderr, "error converting der (%d)\n",
|
|
|
4418f4 |
PORT_GetError());
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
}
|
|
|
4418f4 |
return SECSuccess;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
/* Encodes and adds extensions to the CRL or CRL entries. */
|
|
|
4418f4 |
SECStatus
|
|
|
4418f4 |
SECU_EncodeAndAddExtensionValue(PRArenaPool *arena, void *extHandle,
|
|
|
4418f4 |
void *value, PRBool criticality, int extenType,
|
|
|
4418f4 |
EXTEN_EXT_VALUE_ENCODER EncodeValueFn)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
SECItem encodedValue;
|
|
|
4418f4 |
SECStatus rv;
|
|
|
4418f4 |
|
|
|
4418f4 |
encodedValue.data = NULL;
|
|
|
4418f4 |
encodedValue.len = 0;
|
|
|
4418f4 |
do {
|
|
|
4418f4 |
rv = (*EncodeValueFn)(arena, value, &encodedValue);
|
|
|
4418f4 |
if (rv != SECSuccess)
|
|
|
4418f4 |
break;
|
|
|
4418f4 |
|
|
|
4418f4 |
rv = CERT_AddExtension(extHandle, extenType, &encodedValue,
|
|
|
4418f4 |
criticality, PR_TRUE);
|
|
|
4418f4 |
if (rv != SECSuccess)
|
|
|
4418f4 |
break;
|
|
|
4418f4 |
|
|
|
4418f4 |
} while (0);
|
|
|
4418f4 |
|
|
|
4418f4 |
return (rv);
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
/* Caller ensures that dst is at least item->len*2+1 bytes long */
|
|
|
4418f4 |
void
|
|
|
4418f4 |
SECU_SECItemToHex(const SECItem * item, char * dst)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
if (dst && item && item->data) {
|
|
|
4418f4 |
unsigned char * src = item->data;
|
|
|
4418f4 |
unsigned int len = item->len;
|
|
|
4418f4 |
for (; len > 0; --len, dst += 2) {
|
|
|
4418f4 |
sprintf(dst, "%02x", *src++);
|
|
|
4418f4 |
}
|
|
|
4418f4 |
*dst = '\0';
|
|
|
4418f4 |
}
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
static unsigned char nibble(char c) {
|
|
|
4418f4 |
c = PORT_Tolower(c);
|
|
|
4418f4 |
return ( c >= '0' && c <= '9') ? c - '0' :
|
|
|
4418f4 |
( c >= 'a' && c <= 'f') ? c - 'a' +10 : -1;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
SECStatus
|
|
|
4418f4 |
SECU_SECItemHexStringToBinary(SECItem* srcdest)
|
|
|
4418f4 |
{
|
|
|
4418f4 |
int i;
|
|
|
4418f4 |
|
|
|
4418f4 |
if (!srcdest) {
|
|
|
4418f4 |
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
if (srcdest->len < 4 || (srcdest->len % 2) ) {
|
|
|
4418f4 |
/* too short to convert, or even number of characters */
|
|
|
4418f4 |
PORT_SetError(SEC_ERROR_BAD_DATA);
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
if (PORT_Strncasecmp((const char*)srcdest->data, "0x", 2)) {
|
|
|
4418f4 |
/* wrong prefix */
|
|
|
4418f4 |
PORT_SetError(SEC_ERROR_BAD_DATA);
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
/* 1st pass to check for hex characters */
|
|
|
4418f4 |
for (i=2; i<srcdest->len; i++) {
|
|
|
4418f4 |
char c = PORT_Tolower(srcdest->data[i]);
|
|
|
4418f4 |
if (! ( ( c >= '0' && c <= '9') ||
|
|
|
4418f4 |
( c >= 'a' && c <= 'f')
|
|
|
4418f4 |
) ) {
|
|
|
4418f4 |
PORT_SetError(SEC_ERROR_BAD_DATA);
|
|
|
4418f4 |
return SECFailure;
|
|
|
4418f4 |
}
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
/* 2nd pass to convert */
|
|
|
4418f4 |
for (i=2; i<srcdest->len; i+=2) {
|
|
|
4418f4 |
srcdest->data[(i-2)/2] = (nibble(srcdest->data[i]) << 4) +
|
|
|
4418f4 |
nibble(srcdest->data[i+1]);
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
/* adjust length */
|
|
|
4418f4 |
srcdest->len -= 2;
|
|
|
4418f4 |
srcdest->len /= 2;
|
|
|
4418f4 |
return SECSuccess;
|
|
|
4418f4 |
}
|