📄 secutil.c
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape security libraries. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//*** secutil.c - various functions used by security stuff***/#include "prtypes.h"#include "prtime.h"#include "prlong.h"#include "prerror.h"#include "prprf.h"#include "plgetopt.h"#include "secutil.h"#include "secpkcs7.h"#include <sys/stat.h>#include <stdarg.h>#ifdef XP_UNIX#include <unistd.h>#endif/* for SEC_TraverseNames */#include "cert.h"#include "certt.h"#include "certdb.h"#include "cdbhdl.h"#include "secmod.h"#include "pk11func.h"#include "secoid.h"#include "blapi.h" /* for RNG_RNGInit */static char consoleName[] = {#ifdef XP_UNIX "/dev/tty"#else "CON:"#endif};char *SECU_GetString(int16 error_number){ static char errString[80]; sprintf(errString, "Unknown error string (%d)", error_number); return errString;}void SECU_PrintError(char *progName, char *msg, ...){ va_list args; PRErrorCode err = PORT_GetError(); const char * errString = SECU_Strerror(err); va_start(args, msg); fprintf(stderr, "%s: ", progName); vfprintf(stderr, msg, args); if (errString != NULL && PORT_Strlen(errString) > 0) fprintf(stderr, ": %s\n", errString); else fprintf(stderr, "\n"); va_end(args);}voidSECU_PrintSystemError(char *progName, char *msg, ...){ va_list args; va_start(args, msg); fprintf(stderr, "%s: ", progName); vfprintf(stderr, msg, args); fprintf(stderr, ": %s\n", strerror(errno)); va_end(args);}static voidsecu_ClearPassword(char *p){ if (p) { PORT_Memset(p, 0, PORT_Strlen(p)); PORT_Free(p); }}static SECItem *secu_GetZeroLengthPassword(SECKEYKeyDBHandle *handle){ SECItem *pwitem; SECStatus rv; /* hash the empty string as a password */ pwitem = SECKEY_DeriveKeyDBPassword(handle, ""); if (pwitem == NULL) { return NULL; } /* check to see if this is the right password */ rv = SECKEY_CheckKeyDBPassword(handle, pwitem); if (rv == SECFailure) { return NULL; } return pwitem;}char *SECU_GetPasswordString(void *arg, char *prompt){#ifndef _WINDOWS char *p = NULL; FILE *input, *output; /* open terminal */ input = fopen(consoleName, "r"); if (input == NULL) { fprintf(stderr, "Error opening input terminal for read\n"); return NULL; } output = fopen(consoleName, "w"); if (output == NULL) { fprintf(stderr, "Error opening output terminal for write\n"); return NULL; } p = SEC_GetPassword (input, output, prompt, SEC_BlindCheckPassword); fclose(input); fclose(output); return p;#else /* Win32 version of above. opening the console may fail on windows95, and certainly isn't necessary.. */ char *p = NULL; p = SEC_GetPassword (stdin, stdout, prompt, SEC_BlindCheckPassword); return p;#endif}SECItem *SECU_GetPassword(void *arg, SECKEYKeyDBHandle *handle){ char *p = NULL; SECStatus rv; SECItem *pwitem; /* Check to see if zero length password or not */ pwitem = secu_GetZeroLengthPassword(handle); if (pwitem) { return pwitem; } p = SECU_GetPasswordString(arg,"Password: "); /* Check to see if zero length password or not */ pwitem = secu_GetZeroLengthPassword(handle); if (pwitem) { return pwitem; } /* hash the password */ pwitem = SECKEY_DeriveKeyDBPassword(handle, p); /* clear out the password strings */ secu_ClearPassword(p); if ( pwitem == NULL ) { fprintf(stderr, "Error hashing password\n"); return NULL; } /* confirm the password */ rv = SECKEY_CheckKeyDBPassword(handle, pwitem); if (rv) { fprintf(stderr, "Sorry\n"); SECITEM_ZfreeItem(pwitem, PR_TRUE); return NULL; } return pwitem;}/* * p a s s w o r d _ h a r d c o d e * * A function to use the password passed in the -f(pwfile) argument * of the command line. * After use once, null it out otherwise PKCS11 calls us forever.? * */char *SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg){ unsigned char phrase[200]; PRFileDesc *fd; PRInt32 nb; char *pwFile = arg; int i; if (!pwFile) return 0; if (retry) { return 0; /* no good retrying - the files contents will be the same */ } fd = PR_Open(pwFile, PR_RDONLY, 0); if (!fd) { fprintf(stderr, "No password file \"%s\" exists.\n", pwFile); return NULL; } nb = PR_Read(fd, phrase, sizeof(phrase)); PR_Close(fd); /* handle the Windows EOL case */ i = 0; while (phrase[i] != '\r' && phrase[i] != '\n' && i < nb) i++; phrase[i] = '\0'; if (nb == 0) { fprintf(stderr,"password file contains no data\n"); return NULL; } else { return (char*) PORT_Strdup((char*)phrase); } return (char*) PORT_Strdup((char*)phrase);}char *SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg) { char prompt[255]; secuPWData *pwdata = arg; secuPWData pwnull = { PW_NONE, 0 }; if (arg == NULL) pwdata = &pwnull; if (retry && pwdata->source != PW_NONE) { PR_fprintf(PR_STDERR, "incorrect password entered at command line.\n"); return NULL; } sprintf(prompt, "Enter Password or Pin for \"%s\":", PK11_GetTokenName(slot)); switch (pwdata->source) { case PW_NONE: return SECU_GetPasswordString(NULL, prompt); case PW_FROMFILE: return SECU_FilePasswd(slot, retry, pwdata->data); case PW_PLAINTEXT: return PL_strdup(arg); default: break; } return NULL;}char *secu_InitSlotPassword(PK11SlotInfo *slot, PRBool retry, void *arg){ char *p0 = NULL; char *p1 = NULL; FILE *input, *output; secuPWData *pwdata = arg; if (pwdata->source == PW_NONE) { /* open terminal */#ifdef _WINDOWS input = stdin;#else input = fopen(consoleName, "r");#endif if (input == NULL) { PR_fprintf(PR_STDERR, "Error opening input terminal for read\n"); return NULL; } /* we have no password, so initialize database with one */ PR_fprintf(PR_STDERR, "In order to finish creating your database, you\n"); PR_fprintf(PR_STDERR, "must enter a password which will be used to\n"); PR_fprintf(PR_STDERR, "encrypt this key and any future keys.\n\n"); PR_fprintf(PR_STDERR, "The password must be at least 8 characters long,\n"); PR_fprintf(PR_STDERR, "and must contain at least one non-alphabetic "); PR_fprintf(PR_STDERR, "character.\n\n"); } else if (pwdata->source == PW_FROMFILE) { input = fopen(pwdata->data, "r"); if (input == NULL) { PR_fprintf(PR_STDERR, "Error opening \"%s\" for read\n", pwdata->data); return NULL; } } else { p0 = PL_strdup(pwdata->data); } output = fopen(consoleName, "w"); if (output == NULL) { PR_fprintf(PR_STDERR, "Error opening output terminal for write\n"); return NULL; } for (;;) { if (!p0) { p0 = SEC_GetPassword(input, output, "Enter new password: ", SEC_BlindCheckPassword); } if (pwdata->source == PW_NONE) { p1 = SEC_GetPassword(input, output, "Re-enter password: ", SEC_BlindCheckPassword); } if (pwdata->source != PW_NONE || (PORT_Strcmp(p0, p1) == 0)) { break; } PR_fprintf(PR_STDERR, "Passwords do not match. Try again.\n"); } /* clear out the duplicate password string */ secu_ClearPassword(p1); fclose(input); fclose(output); return p0;}SECStatusSECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile){ SECStatus rv; secuPWData pwdata, newpwdata; char *oldpw = NULL, *newpw = NULL; if (passwd) { pwdata.source = PW_PLAINTEXT; pwdata.data = passwd; } else if (pwFile) { pwdata.source = PW_FROMFILE; pwdata.data = pwFile; } else { pwdata.source = PW_NONE; pwdata.data = NULL; } if (PK11_NeedUserInit(slot)) { newpw = secu_InitSlotPassword(slot, PR_FALSE, &pwdata); rv = PK11_InitPin(slot, (char*)NULL, newpw); goto done; } for (;;) { oldpw = SECU_GetModulePassword(slot, PR_FALSE, &pwdata); if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) { if (pwdata.source == PW_NONE) { PR_fprintf(PR_STDERR, "Invalid password. Try again.\n"); } else { PR_fprintf(PR_STDERR, "Invalid password.\n"); PORT_Memset(oldpw, 0, PL_strlen(oldpw)); PORT_Free(oldpw); return SECFailure; } } else break; PORT_Free(oldpw); } newpwdata.source = PW_NONE; newpwdata.data = NULL; newpw = secu_InitSlotPassword(slot, PR_FALSE, &newpwdata); if (PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) { PR_fprintf(PR_STDERR, "Failed to change password.\n"); return SECFailure; } PORT_Memset(oldpw, 0, PL_strlen(oldpw)); PORT_Free(oldpw); PR_fprintf(PR_STDOUT, "Password changed successfully.\n");done: PORT_Memset(newpw, 0, PL_strlen(newpw)); PORT_Free(newpw); return SECSuccess;}struct matchobj { SECItem index; char *nname; PRBool found;};static SECStatussecu_match_nickname(DBT *k, DBT *d, void *pdata){ struct matchobj *match; unsigned char *buf; char *nname; int nnlen; match = (struct matchobj *)pdata; buf = (unsigned char *)d->data; if (match->found == PR_TRUE) return SECSuccess; nnlen = buf[2]; nname = (char *)(buf + 3 + buf[1]); if (PORT_Strncmp(match->nname, nname, nnlen) == 0) { match->index.len = k->size; match->index.data = PORT_ZAlloc(k->size + 1); PORT_Memcpy(match->index.data, k->data, k->size); match->found = PR_TRUE; } return SECSuccess;}SECItem *SECU_GetKeyIDFromNickname(char *name){ struct matchobj match; SECKEYKeyDBHandle *handle; SECItem *keyid; match.nname = name; match.found = PR_FALSE; handle = SECKEY_GetDefaultKeyDB(); SECKEY_TraverseKeys(handle, secu_match_nickname, &match); if (match.found == PR_FALSE) return NULL; keyid = SECITEM_DupItem(&match.index); return keyid;}PRBoolSECU_CheckKeyNameExists(SECKEYKeyDBHandle *handle, char *nickname){ SECItem *keyid; keyid = SECU_GetKeyIDFromNickname(nickname); if(keyid == NULL) return PR_FALSE; SECITEM_FreeItem(keyid, PR_TRUE); return PR_TRUE;}SECKEYPrivateKey *SECU_FindPrivateKeyFromNickname(char *name){ SECItem * keyid; SECKEYPrivateKey *key; PK11SlotInfo * slot = PK11_GetInternalKeySlot(); SECStatus rv; keyid = SECU_GetKeyIDFromNickname(name); if (keyid == NULL) return NULL; PK11_SetPasswordFunc(SECU_GetModulePassword); if(PK11_NeedLogin(slot) && !PK11_IsLoggedIn(slot,NULL)) { rv = PK11_DoPassword(slot, PR_TRUE, NULL); if (rv != SECSuccess) return NULL; } key = PK11_FindKeyByKeyID(slot, keyid, NULL); SECITEM_FreeItem(keyid, PR_TRUE); return key;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -