static int t_fromb64(unsigned char *a, size_t alen, const char *src)
{
    char *loc;
    int i, j;
    int size;
    while (*src && (*src == ' ' || *src == '\t' || *src == '\n'))
        ++src;
    size = strlen(src);
    if (alen > INT_MAX || size > (int)alen)
        return -1;
    i = 0;
    while (i < size) {
        loc = strchr(b64table, src[i]);
        if (loc == (char *)0)
            break;
        else
            a[i] = loc - b64table;
        ++i;
    }
    if (i == 0)
        return 0;
    size = i;
    i = size - 1;
    j = size;
    while (1) {
        a[j] = a[i];
        if (--i < 0)
            break;
        a[j] |= (a[i] & 3) << 6;
        --j;
        a[j] = (unsigned char)((a[i] & 0x3c) >> 2);
        if (--i < 0)
            break;
        a[j] |= (a[i] & 0xf) << 4;
        --j;
        a[j] = (unsigned char)((a[i] & 0x30) >> 4);
        if (--i < 0)
            break;
        a[j] |= (a[i] << 2);
        a[--j] = 0;
        if (--i < 0)
            break;
    }
    while (a[j] == 0 && j <= size)
        ++j;
    i = 0;
    while (j <= size)
        a[i++] = a[j++];
    return i;
}
['int srp_main(int argc, char **argv)\n{\n    ENGINE *e = NULL;\n    CA_DB *db = NULL;\n    CONF *conf = NULL;\n    int gNindex = -1, maxgN = -1, ret = 1, errors = 0, verbose = 0, i;\n    int doupdatedb = 0, mode = OPT_ERR;\n    char *user = NULL, *passinarg = NULL, *passoutarg = NULL;\n    char *passin = NULL, *passout = NULL, *gN = NULL, *userinfo = NULL;\n    char *randfile = NULL, *section = NULL;\n    char **gNrow = NULL, *configfile = NULL;\n    char *srpvfile = NULL, **pp, *prog;\n    OPTION_CHOICE o;\n    prog = opt_init(argc, argv, srp_options);\n    while ((o = opt_next()) != OPT_EOF) {\n        switch (o) {\n        case OPT_EOF:\n        case OPT_ERR:\n opthelp:\n            BIO_printf(bio_err, "%s: Use -help for summary.\\n", prog);\n            goto end;\n        case OPT_HELP:\n            opt_help(srp_options);\n            ret = 0;\n            goto end;\n        case OPT_VERBOSE:\n            verbose++;\n            break;\n        case OPT_CONFIG:\n            configfile = opt_arg();\n            break;\n        case OPT_NAME:\n            section = opt_arg();\n            break;\n        case OPT_SRPVFILE:\n            srpvfile = opt_arg();\n            break;\n        case OPT_ADD:\n        case OPT_DELETE:\n        case OPT_MODIFY:\n        case OPT_LIST:\n            if (mode != OPT_ERR) {\n                BIO_printf(bio_err,\n                           "%s: Only one of -add/delete-modify/-list\\n",\n                           prog);\n                goto opthelp;\n            }\n            mode = o;\n            break;\n        case OPT_GN:\n            gN = opt_arg();\n            break;\n        case OPT_USERINFO:\n            userinfo = opt_arg();\n            break;\n        case OPT_PASSIN:\n            passinarg = opt_arg();\n            break;\n        case OPT_PASSOUT:\n            passoutarg = opt_arg();\n            break;\n        case OPT_ENGINE:\n            e = setup_engine(opt_arg(), 0);\n            break;\n        }\n    }\n    argc = opt_num_rest();\n    argv = opt_rest();\n    if (srpvfile && configfile) {\n        BIO_printf(bio_err,\n                   "-srpvfile and -configfile cannot be specified together.\\n");\n        goto end;\n    }\n    if (mode == OPT_ERR) {\n        BIO_printf(bio_err,\n                   "Exactly one of the options -add, -delete, -modify -list must be specified.\\n");\n        goto opthelp;\n    }\n    if ((mode == OPT_DELETE || mode == OPT_MODIFY || mode == OPT_ADD)\n        && argc < 1) {\n        BIO_printf(bio_err,\n                   "Need at least one user for options -add, -delete, -modify. \\n");\n        goto opthelp;\n    }\n    if ((passin || passout) && argc != 1) {\n        BIO_printf(bio_err,\n                   "-passin, -passout arguments only valid with one user.\\n");\n        goto opthelp;\n    }\n    if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {\n        BIO_printf(bio_err, "Error getting passwords\\n");\n        goto end;\n    }\n    if (!srpvfile) {\n        if (!configfile)\n            configfile = default_config_file;\n        if (verbose)\n            BIO_printf(bio_err, "Using configuration from %s\\n",\n                       configfile);\n        conf = app_load_config(configfile);\n        if (conf == NULL)\n            goto end;\n        if (configfile != default_config_file && !app_load_modules(conf))\n            goto end;\n        if (section == NULL) {\n            if (verbose)\n                BIO_printf(bio_err,\n                           "trying to read " ENV_DEFAULT_SRP\n                           " in " BASE_SECTION "\\n");\n            section = lookup_conf(conf, BASE_SECTION, ENV_DEFAULT_SRP);\n            if (section == NULL)\n                goto end;\n        }\n        if (randfile == NULL)\n            randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");\n        if (verbose)\n            BIO_printf(bio_err,\n                       "trying to read " ENV_DATABASE " in section \\"%s\\"\\n",\n                       section);\n        srpvfile = lookup_conf(conf, section, ENV_DATABASE);\n        if (srpvfile == NULL)\n            goto end;\n    }\n    if (randfile == NULL)\n        ERR_clear_error();\n    else\n        app_RAND_load_file(randfile, 0);\n    if (verbose)\n        BIO_printf(bio_err, "Trying to read SRP verifier file \\"%s\\"\\n",\n                   srpvfile);\n    db = load_index(srpvfile, NULL);\n    if (db == NULL)\n        goto end;\n    for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {\n        pp = sk_OPENSSL_PSTRING_value(db->db->data, i);\n        if (pp[DB_srptype][0] == DB_SRP_INDEX) {\n            maxgN = i;\n            if ((gNindex < 0) && (gN != NULL) && strcmp(gN, pp[DB_srpid]) == 0)\n                gNindex = i;\n            print_index(db, i, verbose > 1);\n        }\n    }\n    if (verbose)\n        BIO_printf(bio_err, "Database initialised\\n");\n    if (gNindex >= 0) {\n        gNrow = sk_OPENSSL_PSTRING_value(db->db->data, gNindex);\n        print_entry(db, gNindex, verbose > 1, "Default g and N");\n    } else if (maxgN > 0 && !SRP_get_default_gN(gN)) {\n        BIO_printf(bio_err, "No g and N value for index \\"%s\\"\\n", gN);\n        goto end;\n    } else {\n        if (verbose)\n            BIO_printf(bio_err, "Database has no g N information.\\n");\n        gNrow = NULL;\n    }\n    if (verbose > 1)\n        BIO_printf(bio_err, "Starting user processing\\n");\n    if (argc > 0)\n        user = *(argv++);\n    while (mode == OPT_LIST || user) {\n        int userindex = -1;\n        if (user != NULL && verbose > 1)\n            BIO_printf(bio_err, "Processing user \\"%s\\"\\n", user);\n        if ((userindex = get_index(db, user, \'U\')) >= 0) {\n            print_user(db, userindex, (verbose > 0) || mode == OPT_LIST);\n        }\n        if (mode == OPT_LIST) {\n            if (user == NULL) {\n                BIO_printf(bio_err, "List all users\\n");\n                for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {\n                    print_user(db, i, 1);\n                }\n            } else if (userindex < 0) {\n                BIO_printf(bio_err,\n                           "user \\"%s\\" does not exist, ignored. t\\n", user);\n                errors++;\n            }\n        } else if (mode == OPT_ADD) {\n            if (userindex >= 0) {\n                char **row =\n                    sk_OPENSSL_PSTRING_value(db->db->data, userindex);\n                BIO_printf(bio_err, "user \\"%s\\" reactivated.\\n", user);\n                row[DB_srptype][0] = \'V\';\n                doupdatedb = 1;\n            } else {\n                char *row[DB_NUMBER];\n                char *gNid;\n                row[DB_srpverifier] = NULL;\n                row[DB_srpsalt] = NULL;\n                row[DB_srpinfo] = NULL;\n                if (!\n                    (gNid =\n                     srp_create_user(user, &(row[DB_srpverifier]),\n                                     &(row[DB_srpsalt]),\n                                     gNrow ? gNrow[DB_srpsalt] : gN,\n                                     gNrow ? gNrow[DB_srpverifier] : NULL,\n                                     passout, verbose))) {\n                    BIO_printf(bio_err,\n                               "Cannot create srp verifier for user \\"%s\\", operation abandoned .\\n",\n                               user);\n                    errors++;\n                    goto end;\n                }\n                row[DB_srpid] = OPENSSL_strdup(user);\n                row[DB_srptype] = OPENSSL_strdup("v");\n                row[DB_srpgN] = OPENSSL_strdup(gNid);\n                if ((row[DB_srpid] == NULL)\n                    || (row[DB_srpgN] == NULL)\n                    || (row[DB_srptype] == NULL)\n                    || (row[DB_srpverifier] == NULL)\n                    || (row[DB_srpsalt] == NULL)\n                    || (userinfo\n                        && ((row[DB_srpinfo] = OPENSSL_strdup(userinfo)) == NULL))\n                    || !update_index(db, row)) {\n                    OPENSSL_free(row[DB_srpid]);\n                    OPENSSL_free(row[DB_srpgN]);\n                    OPENSSL_free(row[DB_srpinfo]);\n                    OPENSSL_free(row[DB_srptype]);\n                    OPENSSL_free(row[DB_srpverifier]);\n                    OPENSSL_free(row[DB_srpsalt]);\n                    goto end;\n                }\n                doupdatedb = 1;\n            }\n        } else if (mode == OPT_MODIFY) {\n            if (userindex < 0) {\n                BIO_printf(bio_err,\n                           "user \\"%s\\" does not exist, operation ignored.\\n",\n                           user);\n                errors++;\n            } else {\n                char **row =\n                    sk_OPENSSL_PSTRING_value(db->db->data, userindex);\n                char type = row[DB_srptype][0];\n                if (type == \'v\') {\n                    BIO_printf(bio_err,\n                               "user \\"%s\\" already updated, operation ignored.\\n",\n                               user);\n                    errors++;\n                } else {\n                    char *gNid;\n                    if (row[DB_srptype][0] == \'V\') {\n                        int user_gN;\n                        char **irow = NULL;\n                        if (verbose)\n                            BIO_printf(bio_err,\n                                       "Verifying password for user \\"%s\\"\\n",\n                                       user);\n                        if ((user_gN =\n                             get_index(db, row[DB_srpgN], DB_SRP_INDEX)) >= 0)\n                            irow =\n                                sk_OPENSSL_PSTRING_value(db->db->data,\n                                                         userindex);\n                        if (!srp_verify_user\n                            (user, row[DB_srpverifier], row[DB_srpsalt],\n                             irow ? irow[DB_srpsalt] : row[DB_srpgN],\n                             irow ? irow[DB_srpverifier] : NULL, passin,\n                             verbose)) {\n                            BIO_printf(bio_err,\n                                       "Invalid password for user \\"%s\\", operation abandoned.\\n",\n                                       user);\n                            errors++;\n                            goto end;\n                        }\n                    }\n                    if (verbose)\n                        BIO_printf(bio_err, "Password for user \\"%s\\" ok.\\n",\n                                   user);\n                    if (!\n                        (gNid =\n                         srp_create_user(user, &(row[DB_srpverifier]),\n                                         &(row[DB_srpsalt]),\n                                         gNrow ? gNrow[DB_srpsalt] : NULL,\n                                         gNrow ? gNrow[DB_srpverifier] : NULL,\n                                         passout, verbose))) {\n                        BIO_printf(bio_err,\n                                   "Cannot create srp verifier for user \\"%s\\", operation abandoned.\\n",\n                                   user);\n                        errors++;\n                        goto end;\n                    }\n                    row[DB_srptype][0] = \'v\';\n                    row[DB_srpgN] = OPENSSL_strdup(gNid);\n                    if (row[DB_srpid] == NULL\n                        || row[DB_srpgN] == NULL\n                        || row[DB_srptype] == NULL\n                        || row[DB_srpverifier] == NULL\n                        || row[DB_srpsalt] == NULL\n                        || (userinfo\n                            && ((row[DB_srpinfo] = OPENSSL_strdup(userinfo))\n                                == NULL)))\n                        goto end;\n                    doupdatedb = 1;\n                }\n            }\n        } else if (mode == OPT_DELETE) {\n            if (userindex < 0) {\n                BIO_printf(bio_err,\n                           "user \\"%s\\" does not exist, operation ignored. t\\n",\n                           user);\n                errors++;\n            } else {\n                char **xpp = sk_OPENSSL_PSTRING_value(db->db->data, userindex);\n                BIO_printf(bio_err, "user \\"%s\\" revoked. t\\n", user);\n                xpp[DB_srptype][0] = \'R\';\n                doupdatedb = 1;\n            }\n        }\n        if (--argc > 0)\n            user = *(argv++);\n        else {\n            user = NULL;\n        }\n    }\n    if (verbose)\n        BIO_printf(bio_err, "User procession done.\\n");\n    if (doupdatedb) {\n        for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {\n            pp = sk_OPENSSL_PSTRING_value(db->db->data, i);\n            if (pp[DB_srptype][0] == \'v\') {\n                pp[DB_srptype][0] = \'V\';\n                print_user(db, i, verbose);\n            }\n        }\n        if (verbose)\n            BIO_printf(bio_err, "Trying to update srpvfile.\\n");\n        if (!save_index(srpvfile, "new", db))\n            goto end;\n        if (verbose)\n            BIO_printf(bio_err, "Temporary srpvfile created.\\n");\n        if (!rotate_index(srpvfile, "new", "old"))\n            goto end;\n        if (verbose)\n            BIO_printf(bio_err, "srpvfile updated.\\n");\n    }\n    ret = (errors != 0);\n end:\n    if (errors != 0)\n        if (verbose)\n            BIO_printf(bio_err, "User errors %d.\\n", errors);\n    if (verbose)\n        BIO_printf(bio_err, "SRP terminating with code %d.\\n", ret);\n    OPENSSL_free(passin);\n    OPENSSL_free(passout);\n    if (ret)\n        ERR_print_errors(bio_err);\n    if (randfile)\n        app_RAND_write_file(randfile);\n    NCONF_free(conf);\n    free_index(db);\n    release_engine(e);\n    return (ret);\n}', 'static char *srp_create_user(char *user, char **srp_verifier,\n                             char **srp_usersalt, char *g, char *N,\n                             char *passout, int verbose)\n{\n    char password[1024];\n    PW_CB_DATA cb_tmp;\n    char *gNid = NULL;\n    char *salt = NULL;\n    cb_tmp.prompt_info = user;\n    cb_tmp.password = passout;\n    if (password_callback(password, sizeof(password), 1, &cb_tmp) > 0) {\n        if (verbose)\n            BIO_printf(bio_err, "Creating\\n user=\\"%s\\"\\n g=\\"%s\\"\\n N=\\"%s\\"\\n",\n                       user, g, N);\n        if (!\n            (gNid =\n             SRP_create_verifier(user, password, &salt, srp_verifier, N,\n                                 g))) {\n            BIO_printf(bio_err, "Internal error creating SRP verifier\\n");\n        } else\n            *srp_usersalt = salt;\n        if (verbose > 1)\n            BIO_printf(bio_err, "gNid=%s salt =\\"%s\\"\\n verifier =\\"%s\\"\\n", gNid,\n                       salt, *srp_verifier);\n    }\n    return gNid;\n}', 'char *SRP_create_verifier(const char *user, const char *pass, char **salt,\n                          char **verifier, const char *N, const char *g)\n{\n    int len;\n    char *result = NULL, *vf = NULL;\n    const BIGNUM *N_bn = NULL, *g_bn = NULL;\n    BIGNUM *N_bn_alloc = NULL, *g_bn_alloc = NULL, *s = NULL, *v = NULL;\n    unsigned char tmp[MAX_LEN];\n    unsigned char tmp2[MAX_LEN];\n    char *defgNid = NULL;\n    int vfsize = 0;\n    if ((user == NULL) ||\n        (pass == NULL) || (salt == NULL) || (verifier == NULL))\n        goto err;\n    if (N) {\n        if ((len = t_fromb64(tmp, sizeof(tmp), N)) <= 0)\n            goto err;\n        N_bn_alloc = BN_bin2bn(tmp, len, NULL);\n        N_bn = N_bn_alloc;\n        if ((len = t_fromb64(tmp, sizeof(tmp) ,g)) <= 0)\n            goto err;\n        g_bn_alloc = BN_bin2bn(tmp, len, NULL);\n        g_bn = g_bn_alloc;\n        defgNid = "*";\n    } else {\n        SRP_gN *gN = SRP_get_gN_by_id(g, NULL);\n        if (gN == NULL)\n            goto err;\n        N_bn = gN->N;\n        g_bn = gN->g;\n        defgNid = gN->id;\n    }\n    if (*salt == NULL) {\n        if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0)\n            goto err;\n        s = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL);\n    } else {\n        if ((len = t_fromb64(tmp2, sizeof(tmp2), *salt)) <= 0)\n            goto err;\n        s = BN_bin2bn(tmp2, len, NULL);\n    }\n    if (!SRP_create_verifier_BN(user, pass, &s, &v, N_bn, g_bn))\n        goto err;\n    BN_bn2bin(v, tmp);\n    vfsize = BN_num_bytes(v) * 2;\n    if (((vf = OPENSSL_malloc(vfsize)) == NULL))\n        goto err;\n    t_tob64(vf, tmp, BN_num_bytes(v));\n    if (*salt == NULL) {\n        char *tmp_salt;\n        if ((tmp_salt = OPENSSL_malloc(SRP_RANDOM_SALT_LEN * 2)) == NULL) {\n            goto err;\n        }\n        t_tob64(tmp_salt, tmp2, SRP_RANDOM_SALT_LEN);\n        *salt = tmp_salt;\n    }\n    *verifier = vf;\n    vf = NULL;\n    result = defgNid;\n err:\n    BN_free(N_bn_alloc);\n    BN_free(g_bn_alloc);\n    OPENSSL_clear_free(vf, vfsize);\n    BN_clear_free(s);\n    BN_clear_free(v);\n    return result;\n}', "static int t_fromb64(unsigned char *a, size_t alen, const char *src)\n{\n    char *loc;\n    int i, j;\n    int size;\n    while (*src && (*src == ' ' || *src == '\\t' || *src == '\\n'))\n        ++src;\n    size = strlen(src);\n    if (alen > INT_MAX || size > (int)alen)\n        return -1;\n    i = 0;\n    while (i < size) {\n        loc = strchr(b64table, src[i]);\n        if (loc == (char *)0)\n            break;\n        else\n            a[i] = loc - b64table;\n        ++i;\n    }\n    if (i == 0)\n        return 0;\n    size = i;\n    i = size - 1;\n    j = size;\n    while (1) {\n        a[j] = a[i];\n        if (--i < 0)\n            break;\n        a[j] |= (a[i] & 3) << 6;\n        --j;\n        a[j] = (unsigned char)((a[i] & 0x3c) >> 2);\n        if (--i < 0)\n            break;\n        a[j] |= (a[i] & 0xf) << 4;\n        --j;\n        a[j] = (unsigned char)((a[i] & 0x30) >> 4);\n        if (--i < 0)\n            break;\n        a[j] |= (a[i] << 2);\n        a[--j] = 0;\n        if (--i < 0)\n            break;\n    }\n    while (a[j] == 0 && j <= size)\n        ++j;\n    i = 0;\n    while (j <= size)\n        a[i++] = a[j++];\n    return i;\n}"]