diff options
Diffstat (limited to 'security/nss/doc/rst/legacy/nss_sample_code/utiltiies_for_nss_samples')
-rw-r--r-- | security/nss/doc/rst/legacy/nss_sample_code/utiltiies_for_nss_samples/index.rst | 747 |
1 files changed, 747 insertions, 0 deletions
diff --git a/security/nss/doc/rst/legacy/nss_sample_code/utiltiies_for_nss_samples/index.rst b/security/nss/doc/rst/legacy/nss_sample_code/utiltiies_for_nss_samples/index.rst new file mode 100644 index 0000000000..a1df68437e --- /dev/null +++ b/security/nss/doc/rst/legacy/nss_sample_code/utiltiies_for_nss_samples/index.rst @@ -0,0 +1,747 @@ +.. _mozilla_projects_nss_nss_sample_code_utiltiies_for_nss_samples: + +Utilities for nss samples +========================= + +.. _nss_sample_code_0_utilities.: + +`NSS Sample Code 0: Utilities. <#nss_sample_code_0_utilities.>`__ +----------------------------------------------------------------- + +.. container:: + + These utility functions are adapted from those found in the sectool library used by the NSS + security tools and other NSS test applications. + + It shows the following: + + - Read DER from a file. + - Compile file size. + - Get seed From a noise gile. + - Generate random numbers. + - Get a module password. + - Extract the password from a text file. + - Print data as hexadecimal. + +`util.h <#util.h>`__ +~~~~~~~~~~~~~~~~~~~~ + +.. container:: + + .. code:: c + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + + #ifndef _UTIL_H + #define _UTIL_H + + #include <prlog.h> + #include <termios.h> + #include <base64.h> + #include <unistd.h> + #include <sys/stat.h> + #include "util.h" + #include <prprf.h> + #include <prerror.h> + #include <nss.h> + #include <pk11func.h> + + /* + * These utility functions are adapted from those found in + * the sectool library used by the NSS security tools and + * other NSS test applications. + */ + + typedef struct { + enum { + PW_NONE = 0, /* no password */ + PW_FROMFILE = 1, /* password stored in a file */ + PW_PLAINTEXT = 2 /* plain-text password passed in buffer */ + /* PW_EXTERNAL = 3 */ + } source; + char *data; + /* depending on source this can be the actual + * password or the file to read it from + */ + } secuPWData; + + /* + * PrintAsAscii + */ + extern void + PrintAsAscii(PRFileDesc* out, const unsigned char *data, unsigned int len); + + /* + * PrintAsHex + */ + extern void + PrintAsHex(PRFileDesc* out, const unsigned char *data, unsigned int len); + + /* + * GetDigit + */ + extern int + GetDigit(char c); + + /* + * HexToBuf + */ + extern int + HexToBuf(unsigned char *inString, SECItem *outbuf, PRBool isHexData); + + /* + * FileToItem + */ + extern SECStatus + FileToItem(SECItem *dst, PRFileDesc *src); + + /* + * CheckPassword + */ + extern PRBool + CheckPassword(char *cp); + + /* + * GetPassword + */ + extern char * + GetPassword(FILE *input, + FILE *output, + char *prompt, + PRBool (*ok)(char *)); + + /* + * FilePasswd extracts the password from a text file + * + * Storing passwords is often used with server environments + * where prompting the user for a password or requiring it + * to be entered in the commnd line is not a feasible option. + * + * This function supports password extraction from files with + * multipe passwords, one for each token. In the single password + * case a line would just have the passord whereas in the multi- + * password variant they could be of the form + * + * token_1_name:its_password + * token_2_name:its_password + * + */ + extern char * + FilePasswd(PK11SlotInfo * + slot, PRBool retry, void *arg); + + /* + * GetModulePassword + */ + extern char * + GetModulePassword(PK11SlotInfo *slot, + int retry, + void *pwdata); + + /* + * GenerateRandom + */ + extern SECStatus + GenerateRandom(unsigned char *rbuf, + int rsize); + + /* + * FileToItem + */ + extern SECStatus + FileToItem(SECItem *dst, + PRFileDesc *src); + + /* + * SeedFromNoiseFile + */ + extern SECStatus + SeedFromNoiseFile(const char *noiseFileName); + + /* + * FileSize + */ + extern long + FileSize(const char* filename); + + /* + * ReadDERFromFile + */ + extern SECStatus + ReadDERFromFile(SECItem *der, const char *inFileName, PRBool ascii); + + #endif /* _UTIL_H */ + +`Util.c <#util.c>`__ +~~~~~~~~~~~~~~~~~~~~ + +.. container:: + + .. code:: c + + /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + + #include "util.h" + + /* + * These utility functions are adapted from those found in + * the sectool library used by the NSS security tools and + * other NSS test applications. + */ + + /* + * Newline + */ + static void + Newline(PRFileDesc* out) + { + PR_fprintf(out, "\n"); + } + + /* + * PrintAsAscii + */ + void + PrintAsAscii(PRFileDesc* out, const unsigned char *data, unsigned int len) + { + char *b64Data = NULL; + + b64Data = BTOA_DataToAscii(data, len); + PR_fprintf(out, "%s", b64Data); + PR_fprintf(out, "\n"); + if (b64Data) { + PORT_Free(b64Data); + } + } + + /* + * PrintAsHex + */ + void + PrintAsHex(PRFileDesc* out, const unsigned char *data, unsigned int len) + { + unsigned i; + int column; + unsigned int limit = 15; + unsigned int level = 1; + + column = level; + if (!len) { + PR_fprintf(out, "(empty)\n"); + return; + } + + for (i = 0; i < len; i++) { + if (i != len - 1) { + PR_fprintf(out, "%02x:", data[i]); + column += 3; + } else { + PR_fprintf(out, "%02x", data[i]); + column += 2; + break; + } + if (column > 76 || (i % 16 == limit)) { + Newline(out); + column = level; + limit = i % 16; + } + } + if (column != level) { + Newline(out); + } + } + + /* + * GetDigit + */ + int + GetDigit(char c) + { + if (c == 0) { + return -1; + } + if (c <= '9' && c >= '0') { + return c - '0'; + } + if (c <= 'f' && c >= 'a') { + return c - 'a' + 0xa; + } + if (c <= 'F' && c >= 'A') { + return c - 'A' + 0xa; + } + return -1; + } + + /* + * HexToBuf + */ + int + HexToBuf(unsigned char *inString, SECItem *outbuf, PRBool isHexData) + { + int len = strlen((const char *)inString); + int outLen = len+1/2; + int trueLen = 0; + int digit1, digit2; + + outbuf->data = isHexData + ? PORT_Alloc(outLen) + : PORT_Alloc(len); + if (!outbuf->data) { + return -1; + } + if (isHexData) { + while (*inString) { + if ((*inString == '\n') || (*inString == ':')) { + inString++; + continue; + } + digit1 = GetDigit(*inString++); + digit2 = GetDigit(*inString++); + if ((digit1 == -1) || (digit2 == -1)) { + PORT_Free(outbuf->data); + outbuf->data = NULL; + return -1; + } + outbuf->data[trueLen++] = digit1 << 4 | digit2; + } + } else { + while (*inString) { + if (*inString == '\n') { + inString++; + continue; + } + outbuf->data[trueLen++] = *inString++; + } + outbuf->data[trueLen] = '\0'; + trueLen = trueLen-1; + } + outbuf->len = trueLen; + return 0; + } + + /* + * FileToItem + */ + SECStatus + FileToItem(SECItem *dst, PRFileDesc *src) + { + PRFileInfo info; + PRInt32 numBytes; + PRStatus prStatus; + + prStatus = PR_GetOpenFileInfo(src, &info); + + if (prStatus != PR_SUCCESS) { + return SECFailure; + } + + dst->data = 0; + if (SECITEM_AllocItem(NULL, dst, info.size)) { + numBytes = PR_Read(src, dst->data, info.size); + if (numBytes == info.size) { + return SECSuccess; + } + } + SECITEM_FreeItem(dst, PR_FALSE); + dst->data = NULL; + return SECFailure; + } + + /* + * echoOff + */ + static void echoOff(int fd) + { + if (isatty(fd)) { + struct termios tio; + tcgetattr(fd, &tio); + tio.c_lflag &= ~ECHO; + tcsetattr(fd, TCSAFLUSH, &tio); + } + } + + /* + * echoOn + */ + static void echoOn(int fd) + { + if (isatty(fd)) { + struct termios tio; + tcgetattr(fd, &tio); + tio.c_lflag |= ECHO; + tcsetattr(fd, TCSAFLUSH, &tio); + } + } + + /* + * CheckPassword + */ + PRBool CheckPassword(char *cp) + { + int len; + char *end; + len = PORT_Strlen(cp); + if (len < 8) { + return PR_FALSE; + } + end = cp + len; + while (cp < end) { + unsigned char ch = *cp++; + if (!((ch >= 'A') && (ch <= 'Z')) && + !((ch >= 'a') && (ch <= 'z'))) { + return PR_TRUE; + } + } + return PR_FALSE; + } + + /* + * GetPassword + */ + char* GetPassword(FILE *input, FILE *output, char *prompt, + PRBool (*ok)(char *)) + { + char phrase[200] = {'\0'}; + int infd = fileno(input); + int isTTY = isatty(infd); + + for (;;) { + /* Prompt for password */ + if (isTTY) { + fprintf(output, "%s", prompt); + fflush (output); + echoOff(infd); + } + fgets(phrase, sizeof(phrase), input); + if (isTTY) { + fprintf(output, "\n"); + echoOn(infd); + } + /* stomp on newline */ + phrase[PORT_Strlen(phrase)-1] = 0; + /* Validate password */ + if (!(*ok)(phrase)) { + 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; + } + return (char*) PORT_Strdup(phrase); + } + } + + /* + * FilePasswd extracts the password from a text file + * + * Storing passwords is often used with server environments + * where prompting the user for a password or requiring it + * to be entered in the commnd line is not a feasible option. + * + * This function supports password extraction from files with + * multipe passwords, one for each token. In the single password + * case a line would just have the passord whereas in the multi- + * password variant they could be of the form + * + * token_1_name:its_password + * token_2_name:its_password + * + */ + char * + FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg) + { + char* phrases, *phrase; + PRFileDesc *fd; + PRInt32 nb; + char *pwFile = arg; + int i; + const long maxPwdFileSize = 4096; + char* tokenName = NULL; + int tokenLen = 0; + + if (!pwFile) + return 0; + + if (retry) { + return 0; /* no good retrying - the files contents will be the same */ + } + + phrases = PORT_ZAlloc(maxPwdFileSize); + + if (!phrases) { + return 0; /* out of memory */ + } + + fd = PR_Open(pwFile, PR_RDONLY, 0); + if (!fd) { + fprintf(stderr, "No password file \"%s\" exists.\n", pwFile); + PORT_Free(phrases); + return NULL; + } + + nb = PR_Read(fd, phrases, maxPwdFileSize); + + PR_Close(fd); + + if (nb == 0) { + fprintf(stderr,"password file contains no data\n"); + PORT_Free(phrases); + return NULL; + } + + if (slot) { + tokenName = PK11_GetTokenName(slot); + if (tokenName) { + tokenLen = PORT_Strlen(tokenName); + } + } + i = 0; + do { + int startphrase = i; + int phraseLen; + + /* handle the Windows EOL case */ + while (phrases[i] != '\r' && phrases[i] != '\n' && i < nb) i++; + + /* terminate passphrase */ + phrases[i++] = '\0'; + /* clean up any EOL before the start of the next passphrase */ + while ( (i<nb) && (phrases[i] == '\r' || phrases[i] == '\n')) { + phrases[i++] = '\0'; + } + /* now analyze the current passphrase */ + phrase = &phrases[startphrase]; + if (!tokenName) + break; + if (PORT_Strncmp(phrase, tokenName, tokenLen)) continue; + phraseLen = PORT_Strlen(phrase); + if (phraseLen < (tokenLen+1)) continue; + if (phrase[tokenLen] != ':') continue; + phrase = &phrase[tokenLen+1]; + break; + + } while (i<nb); + + phrase = PORT_Strdup((char*)phrase); + PORT_Free(phrases); + return phrase; + } + + /* + * GetModulePassword + */ + char* GetModulePassword(PK11SlotInfo *slot, int retry, void *arg) + { + char prompt[255]; + secuPWData *pwdata = (secuPWData *)arg; + char *pw; + + if (pwdata == NULL) { + return NULL; + } + + if (retry && pwdata->source != PW_NONE) { + PR_fprintf(PR_STDERR, "Incorrect password/PIN entered.\n"); + return NULL; + } + + switch (pwdata->source) { + case PW_NONE: + sprintf(prompt, "Enter Password or Pin for \"%s\":", + PK11_GetTokenName(slot)); + return GetPassword(stdin, stdout, prompt, CheckPassword); + case PW_FROMFILE: + pw = FilePasswd(slot, retry, pwdata->data); + pwdata->source = PW_PLAINTEXT; + pwdata->data = PL_strdup(pw); + return pw; + case PW_PLAINTEXT: + return PL_strdup(pwdata->data); + default: + break; + } + PR_fprintf(PR_STDERR, "Password check failed: No password found.\n"); + return NULL; + } + + /* + * GenerateRandom + */ + SECStatus + GenerateRandom(unsigned char *rbuf, int rsize) + { + char meter[] = { + "\r| |" }; + int fd, count; + int c; + SECStatus rv = SECSuccess; + cc_t orig_cc_min; + cc_t orig_cc_time; + tcflag_t orig_lflag; + struct termios tio; + + fprintf(stderr, "To generate random numbers, " + "continue typing until the progress meter is full:\n\n"); + fprintf(stderr, "%s", meter); + fprintf(stderr, "\r|"); + + /* turn off echo on stdin & return on 1 char instead of NL */ + fd = fileno(stdin); + + tcgetattr(fd, &tio); + orig_lflag = tio.c_lflag; + orig_cc_min = tio.c_cc[VMIN]; + orig_cc_time = tio.c_cc[VTIME]; + tio.c_lflag &= ~ECHO; + tio.c_lflag &= ~ICANON; + tio.c_cc[VMIN] = 1; + tio.c_cc[VTIME] = 0; + tcsetattr(fd, TCSAFLUSH, &tio); + /* Get random noise from keyboard strokes */ + count = 0; + while (count < rsize) { + c = getc(stdin); + if (c == EOF) { + rv = SECFailure; + break; + } + *(rbuf + count) = c; + if (count == 0 || c != *(rbuf + count -1)) { + count++; + fprintf(stderr, "*"); + } + } + rbuf[count] = '\0'; + + fprintf(stderr, "\n\nFinished. Press enter to continue: "); + while ((c = getc(stdin)) != '\n' && c != EOF) + ; + if (c == EOF) + rv = SECFailure; + fprintf(stderr, "\n"); + + /* set back termio the way it was */ + tio.c_lflag = orig_lflag; + tio.c_cc[VMIN] = orig_cc_min; + tio.c_cc[VTIME] = orig_cc_time; + tcsetattr(fd, TCSAFLUSH, &tio); + return rv; + } + + /* + * SeedFromNoiseFile + */ + SECStatus + SeedFromNoiseFile(const char *noiseFileName) + { + char buf[2048]; + PRFileDesc *fd; + PRInt32 count; + + fd = PR_Open(noiseFileName, PR_RDONLY, 0); + if (!fd) { + fprintf(stderr, "failed to open noise file."); + return SECFailure; + } + + do { + count = PR_Read(fd,buf,sizeof(buf)); + if (count > 0) { + PK11_RandomUpdate(buf,count); + } + } while (count > 0); + + PR_Close(fd); + return SECSuccess; + } + + /* + * FileSize + */ + long FileSize(const char* filename) + { + struct stat stbuf; + stat(filename, &stbuf); + return stbuf.st_size; + } + + /* + * ReadDERFromFile + */ + SECStatus + ReadDERFromFile(SECItem *der, const char *inFileName, PRBool ascii) + { + SECStatus rv = SECSuccess; + PRFileDesc *inFile = NULL; + + inFile = PR_Open(inFileName, PR_RDONLY, 0); + if (!inFile) { + PR_fprintf(PR_STDERR, "Failed to open file \"%s\" (%ld, %ld).\n", + inFileName, PR_GetError(), PR_GetOSError()); + rv = SECFailure; + goto cleanup; + } + + if (ascii) { + /* First convert ascii to binary */ + SECItem filedata; + char *asc, *body; + + /* Read in ascii data */ + rv = FileToItem(&filedata, inFile); + asc = (char *)filedata.data; + if (!asc) { + PR_fprintf(PR_STDERR, "unable to read data from input file\n"); + rv = SECFailure; + goto cleanup; + } + + /* check for headers and trailers and remove them */ + if ((body = strstr(asc, "-----BEGIN")) != NULL) { + char *trailer = NULL; + asc = body; + body = PORT_Strchr(body, '\n'); + if (!body) + body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */ + if (body) + trailer = strstr(++body, "-----END"); + if (trailer != NULL) { + *trailer = '\0'; + } else { + PR_fprintf(PR_STDERR, "input has header but no trailer\n"); + PORT_Free(filedata.data); + rv = SECFailure; + goto cleanup; + } + } else { + body = asc; + } + + /* Convert to binary */ + rv = ATOB_ConvertAsciiToItem(der, body); + if (rv) { + PR_fprintf(PR_STDERR, "error converting ascii to binary %s\n", + PORT_GetError()); + PORT_Free(filedata.data); + rv = SECFailure; + goto cleanup; + } + + PORT_Free(filedata.data); + } else { + /* Read in binary der */ + rv = FileToItem(der, inFile); + if (rv) { + PR_fprintf(PR_STDERR, "error converting der \n"); + rv = SECFailure; + } + } + cleanup: + if (inFile) { + PR_Close(inFile); + } + return rv; + }
\ No newline at end of file |