summaryrefslogtreecommitdiff
path: root/doc/rst/legacy/nss_sample_code/nss_sample_code_utililies_1/index.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/rst/legacy/nss_sample_code/nss_sample_code_utililies_1/index.rst')
-rw-r--r--doc/rst/legacy/nss_sample_code/nss_sample_code_utililies_1/index.rst553
1 files changed, 553 insertions, 0 deletions
diff --git a/doc/rst/legacy/nss_sample_code/nss_sample_code_utililies_1/index.rst b/doc/rst/legacy/nss_sample_code/nss_sample_code_utililies_1/index.rst
new file mode 100644
index 000000000..74526878f
--- /dev/null
+++ b/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:: notranslate
+
+ #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="&amp;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