diff options
Diffstat (limited to 'security/nss/doc/rst/legacy/nss_sample_code/nss_sample_code_utililies_1/index.rst')
-rw-r--r-- | security/nss/doc/rst/legacy/nss_sample_code/nss_sample_code_utililies_1/index.rst | 553 |
1 files changed, 553 insertions, 0 deletions
diff --git a/security/nss/doc/rst/legacy/nss_sample_code/nss_sample_code_utililies_1/index.rst b/security/nss/doc/rst/legacy/nss_sample_code/nss_sample_code_utililies_1/index.rst new file mode 100644 index 0000000000..261b587f9f --- /dev/null +++ b/security/nss/doc/rst/legacy/nss_sample_code/nss_sample_code_utililies_1/index.rst @@ -0,0 +1,553 @@ +.. _mozilla_projects_nss_nss_sample_code_nss_sample_code_utililies_1: + +NSS Sample Code Utilities_1 +=========================== + +.. _nss_sample_code_common_utilities: + +`NSS Sample Code Common: Utilities <#nss_sample_code_common_utilities>`__ +------------------------------------------------------------------------- + +.. container:: + + This is a library of utilities used by many of the samples. This code shows the following: + + - Extract seed from noise file + - Read DER encoding from a file + - Extract the password from a text file + - Get the module password + - Print as ascii or hexadecimal + +.. _sample_code: + +`Sample Code <#sample_code>`__ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. container:: + + .. code:: + + #include <prlog.h> + #include <termios.h> + #include <base64.h> + #include <unistd.h> + #include <sys/stat.h> + #include <prprf.h> + #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(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 command line is not a feasible option. + * + * This function supports password extraction from files with + * multiple passwords, one for each token. In the single password + * case a line would just have the password 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 file 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) analyze="" char="" current="" getmodulepassword="" if="" int="" now="" passphrase="" phrase="&phrases[startphrase];" phraselen="" pk11slotinfo="" pwdata="=" pwdata-="" retry="" return="" secupwdata="" the="" void="" while="">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; + } + + </nb)>
\ No newline at end of file |