NSS Sample Code Sample_2_Initialization of NSS

NSS Sample Code 2: Initializing NSS

Эта программа демонстрирует как инициализировать NSS Database. Так же эта программа иллюстрирует обработку пароля.

Пример NSS инициализации и обработки пароля

/* NSPR Заголовки*/
#include <prthread.h>
#include <plgetopt.h>
#include <prprf.h>

/* NSS Заголовки */
#include <nss.h>
#include <pk11func.h>

#include "util.h"

// для того, чтобы русские буквы отображались корректно используйте setlocale(LC_ALL,"RUS") в main() :)

/* Вывести сообщение о том, какая база данных используется и выйти */
static void Usage(const char *progName)
{
    fprintf(stderr, "\nИспользуется:  %s -d <dbdirpath> [-p <plainpasswc>]"
                    " [-f <passwdffile>]\n\n",
                    progName);
    fprintf(stderr, "%-15s Укажите путь к каталогу базы данных\n\n",
             "-d <dbdirpath>");
    fprintf(stderr, "%-15s Укажите незашифрованный пароль\n\n",
             "-p <plainpasswc>");
    fprintf(stderr, "%-15s Укажите файл с паролями\n\n",
             "-f <plainpasswc>");
    exit(-1);
}

/* Инициализация пароля слота*/
char *InitSlotPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
{
   FILE       *input;
   FILE       *output;
   char       *p0            = NULL;
   char       *p1            = NULL;
   secuPWData *pwdata        = (secuPWData *) arg;

   if (pwdata->source == PW_FROMFILE) {
       return FilePasswd(slot, retry, pwdata->data);
   }
   if (pwdata->source == PW_PLAINTEXT) {
       return PL_strdup(pwdata->data);
   }

   /* Открыть терминал (linux)*/
   input = fopen("/dev/tty", "r");
   if (input == NULL) {
       PR_fprintf(PR_STDERR, "Ошибка открытия терминала для чтения\n");
       return NULL;
   }
   
   /* У нас нет паролей, давайте инициализируем базу данных*/
   PR_fprintf(PR_STDERR,
       "Введите пароль который будет закодирован вашим ключом.\n"
       "Пароль должен быть длиннее восьми символов ,\n"
       "И содержать хотя бы одну букву из алфавита.\n\n");

   output = fopen("/dev/tty", "w");
   if (output == NULL) {
       PR_fprintf(PR_STDERR, "Ошибка открытия консоли для записи\n");
       return NULL;
   }

   for (;;) {
       if (p0)
           PORT_Free(p0);
       p0 = GetPassword(input, output, "Введите новый пароль: ",
                                                CheckPassword);
       if (p1)
           PORT_Free(p1);
       p1 = GetPassword(input, output, "Введите пароль повторно: ",
                                                CheckPassword);
       if (p0 && p1 && !PORT_Strcmp(p0, p1)) {
           break;
       }
       PR_fprintf(PR_STDERR, "Пароли не совпадают. Попробуйте ещё раз.\n");
   }
  
   /* Убрать дубликат пароля из строки*/
   if (p1) {
       PORT_Memset(p1, 0, PORT_Strlen(p1));
       PORT_Free(p1);
   }
   fclose(input);
   fclose(output);

   return p0;
}
       
/* Смена пароля */
SECStatus ChangePW(PK11SlotInfo *slot, char *oldPass, char *newPass,
                   char *oldPwFile, char *newPwFile)
{
    SECStatus rv;
    secuPWData pwdata;
    secuPWData newpwdata;
    char      *oldpw = NULL;
    char      *newpw = NULL;

    if (oldPass) {
        pwdata.source = PW_PLAINTEXT;
        pwdata.data = oldPass;
    } else if (oldPwFile) {
        pwdata.source = PW_FROMFILE;
        pwdata.data = oldPwFile;
    } else {
        pwdata.source = PW_NONE;
        pwdata.data = NULL;
    }

    if (newPass) {
        newpwdata.source = PW_PLAINTEXT;
        newpwdata.data = newPass;
    } else if (newPwFile) {
        newpwdata.source = PW_FROMFILE;
        newpwdata.data = NULL;
    } else {
        newpwdata.source = PW_NONE;
        newpwdata.data = NULL;
    }

    if (PK11_NeedUserInit(slot)) {
        newpw = InitSlotPassword(slot, PR_FALSE, &pwdata);
        rv = PK11_InitPin(slot, (char*)NULL, newpw);
    } 
    else {
        for (;;) {
            oldpw = 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);
        }
        newpw = InitSlotPassword(slot, PR_FALSE, &newpwdata); 

        if (PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) {
            PR_fprintf(PR_STDERR, "Не получилось изменить пароль.\n");
            return SECFailure;
        }
        PORT_Memset(oldpw, 0, PL_strlen(oldpw));
        PORT_Free(oldpw);
        PR_fprintf(PR_STDOUT, "Пароль изменён успешно!.\n");
    }
    PORT_Memset(newpw, 0, PL_strlen(newpw));
    PORT_Free(newpw);
    return SECSuccess;
}
    
/*
 * Этот пример показывает как инициализировать nss базу данных.
 * Он создаёт новую nss конфигурационную директорию с пустой базой данных
 * и инициализирует базы данных. Так же он показывает методы
 * для обработки пароля.
 */
int main(int argc, char **argv)
{
    PLOptState     *optstate;
    PLOptStatus    status;
    SECStatus      rv;
    SECStatus      rvShutdown;
    char           *slotname    = "internal";
    PK11SlotInfo   *slot        = NULL;
    char           *dbdir       = NULL;
    char           *plainPass   = NULL;
    char           *pwFile      = NULL;

    char * progName = strrchr(argv[0], '/');
    progName = progName ? progName + 1 : argv[0];

    /* Копирование аргументов командной строки */
    optstate = PL_CreateOptState(argc, argv, "d:p:q:f:g:");
    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
        switch (optstate->option) {
        case 'd':
             dbdir = strdup(optstate->value);
             break;
        case 'p':
             plainPass = strdup(optstate->value);
             break;
        case 'f':
             pwFile = strdup(optstate->value);
             break;
        default:
             Usage(progName);
             break;
        }
    }
    PL_DestroyOptState(optstate);

    if (!dbdir)
        Usage(progName);

    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);

    /* Создать базу данных */
    rv = NSS_InitReadWrite(dbdir); 
    if (rv != SECSuccess) {
        PR_fprintf(PR_STDERR, "NSS_Initialize Failed ( не получилось инициализировать nss )");
        PR_Cleanup();
        exit(rv);
    } 

    if (PL_strcmp(slotname, "internal") == 0)
        slot = PK11_GetInternalKeySlot();
    
    /* Если создаётся новая база данных, инициализируем пароль.*/
    rv = ChangePW(slot, plainPass, 0, pwFile, 0);
    if (rv != SECSuccess) {
        PR_fprintf(PR_STDERR, "Не получилось  сменить пароль\n");
    }

    if (slot) {
        PK11_FreeSlot(slot);
    }
    rvShutdown = NSS_Shutdown();
    if (rvShutdown != SECSuccess) {
        PR_fprintf(PR_STDERR, "Failed : NSS_Shutdown() ( ошибка : выключение nss )\n");
        rv = SECFailure;
    }

    PR_Cleanup();

    return rv;
}
</plainpasswc></plainpasswc></dbdirpath></passwdffile></plainpasswc></dbdirpath></pk11func.h></nss.h></prprf.h></plgetopt.h></prthread.h>

Метки документа и участники

Внесли вклад в эту страницу: IlkaPoilka
Обновлялась последний раз: IlkaPoilka,