void TestAuth::testSaltGeneration() { char salt[32 + 1] = { 0 }; size_t max_size = sizeof(salt); CPPUNIT_ASSERT(1 < strlen(EMPTY_SALT)); // condition for the next test CPPUNIT_ASSERT(generate_salt(salt, 1) == -1); // shouldn't fill buffer if it's lesst than EMPTY_SALT CPPUNIT_ASSERT(max_size > strlen(EMPTY_SALT)); // condition for the next tests CPPUNIT_ASSERT(generate_salt(salt, strlen(EMPTY_SALT) + 1) == 0); CPPUNIT_ASSERT(strcmp(salt, EMPTY_SALT) == 0); // since generate_salt() is random, we're doing reasonable set of checks for valid salt for (int i = 0; i < 100; ++i) { memset(salt, 0, sizeof(salt)); CPPUNIT_ASSERT(generate_salt(salt, max_size) == 0); CPPUNIT_ASSERT(strlen(salt) == max_size - 1); CPPUNIT_ASSERT(strstr(salt, EMPTY_SALT) == salt); for (size_t j = strlen(EMPTY_SALT); j < strlen(salt); ++j) { CPPUNIT_ASSERT(isalnum(salt[j]) != 0 || salt[j] == '.' || salt[j] == '/'); } } }
/** \brief Implementation of encrypt function. * * @param src Source chars. * @param srclen Length of source in chars. * @return Newly allocated encrypted string. */ static char* encrypt_2chan(const char *src, size_t srclen) { char salt[3], enc[14], *str = create_safe_cstr_buffer(srclen); generate_salt(salt, str, src, srclen); DES_fcrypt(str, salt, enc); free(str); return memdup(enc + 3, 11); }
static int build_reauthorize_challenge (const char *user, const char *secret, char **challenge) { int ret; char *nonce = NULL; char *hex = NULL; ssize_t salt_len; int len; salt_len = parse_salt (secret); if (salt_len < 0) { message ("ignoring invalid reauthorize secret"); ret = -EINVAL; goto out; } ret = generate_salt (&nonce); if (ret < 0) { errno = -ret; message ("unable to generate crypt salt: %m"); goto out; } ret = hex_encode (user, -1, &hex); if (ret < 0) { errno = -ret; message ("couldn't encode user as hex: %m"); goto out; } len = asprintf (challenge, "crypt1:%s:%s:%.*s", hex, nonce, (int)salt_len, secret); if (len < 0) { message ("failed to allocate challenge"); ret = -ENOMEM; goto out; } /* Double check that we didn't include the whole secret */ assert ((*challenge)[len - 1] == '$'); assert (strstr (*challenge, secret) == NULL); ret = 0; out: free (nonce); free (hex); return ret; }
void TestAuth::setUp() { init_rfsd_instance(&m_instance); // prepare in-memory passwd database const char *valid_user[2] = { "root", "root" }; CPPUNIT_ASSERT(add_or_replace_auth(&m_instance.passwd.auths, valid_user[0], valid_user[1]) == 0); // prepare auth in server's instance m_instance.server.auth_user = strdup(valid_user[0]); CPPUNIT_ASSERT(generate_salt(m_instance.server.auth_salt, sizeof(m_instance.server.auth_salt)) == 0); m_instance.server.auth_passwd = passwd_hash(get_auth_password(m_instance.passwd.auths, valid_user[0]), m_instance.server.auth_salt); CPPUNIT_ASSERT(m_instance.server.auth_passwd != NULL); }
/** \brief Implementation of the test function. * * @param src Source chars. * @param srclen Length of source in chars. * @param print File to print into. * @return Number of tests done. */ static int test_2chan(const char *src, size_t srclen, FILE *print) { char salt[3], enc[14], cmp[11], *str = create_safe_cstr_buffer(srclen); generate_salt(salt, str, src, srclen); DES_fcrypt(str, salt, enc); trip_transform(cmp, enc + 3, 10); trip_compare(src, enc + 3, cmp, 10, print); free(str); return 1; }
std::string sum(const std::string &data) { return compute_hash(data, generate_salt()); }
boost::tuple<shared_data::action, client_info> shared_data::process_user(const std::string& uname, const std::string& phash, int session_id) { boost::mutex::scoped_lock lock(guard_); // XXX Get password from database. // if(lookup_username_in_database_fails) { // return boost::make_tuple(user_not_found, it->second); // } auto it = clients_.find(uname); if(session_id == -1) { // No session id, check if user name in list already. if(it == clients_.end()) { // User name not in list. Let's add it. auto ret = clients_.insert(std::pair<std::string, client_info>(uname, client_info(generate_session_id(), true, generate_salt()))); it = ret.first; } } else { if(it == clients_.end()) { // user not in list, but we've got a session id. Expire session and generate a new id. auto ret = clients_.insert(std::pair<std::string, client_info>(uname, client_info(generate_session_id(), true, generate_salt()))); it = ret.first; } else { // We have been sent a session_id, check if it's valid. if(it->second.session_id != session_id) { it->second.signed_in = false; return boost::make_tuple(bad_session_id, it->second); } } } if(phash.empty()) { return boost::make_tuple(send_salt, it->second); } else { if(check_password(it->second.salt, fixed_password, phash)) { it->second.signed_in = true; return boost::make_tuple(login_success, it->second); } else { it->second.signed_in = false; return boost::make_tuple(password_failed, it->second); } } }
int main(int argc, char *argv[]) { int ch, i; int password_fd = -1; unsigned int salt_minlen = 0; unsigned int salt_maxlen = 0; unsigned int rounds_support = 0; const char *salt_prefix = NULL; const char *salt_arg = NULL; unsigned int rounds = 0; char *salt = NULL; char rounds_str[30]; char *password = NULL; #ifdef ENABLE_NLS setlocale(LC_ALL, ""); bindtextdomain(NLS_CAT_NAME, LOCALEDIR); textdomain(NLS_CAT_NAME); #endif /* prepend options from environment */ argv = merge_args(getenv("MKPASSWD_OPTIONS"), argv, &argc); while ((ch = GETOPT_LONGISH(argc, argv, "hH:m:5P:R:sS:V", longopts, 0)) > 0) { switch (ch) { case '5': optarg = (char *) "md5"; /* fall through */ case 'm': case 'H': if (!optarg || strcaseeq("help", optarg)) { display_methods(); exit(0); } for (i = 0; methods[i].method != NULL; i++) if (strcaseeq(methods[i].method, optarg)) { salt_prefix = methods[i].prefix; salt_minlen = methods[i].minlen; salt_maxlen = methods[i].maxlen; rounds_support = methods[i].rounds; break; } if (!salt_prefix) { fprintf(stderr, _("Invalid method '%s'.\n"), optarg); exit(1); } break; case 'P': { char *p; password_fd = strtol(optarg, &p, 10); if (p == NULL || *p != '\0' || password_fd < 0) { fprintf(stderr, _("Invalid number '%s'.\n"), optarg); exit(1); } } break; case 'R': { char *p; long r; r = strtol(optarg, &p, 10); if (p == NULL || *p != '\0' || r < 0) { fprintf(stderr, _("Invalid number '%s'.\n"), optarg); exit(1); } rounds = r; } break; case 's': password_fd = 0; break; case 'S': salt_arg = optarg; break; case 'V': display_version(); exit(0); case 'h': display_help(EXIT_SUCCESS); default: fprintf(stderr, _("Try '%s --help' for more information.\n"), argv[0]); exit(1); } } argc -= optind; argv += optind; if (argc == 2 && !salt_arg) { password = argv[0]; salt_arg = argv[1]; } else if (argc == 1) { password = argv[0]; } else if (argc == 0) { } else { display_help(EXIT_FAILURE); } /* default: DES password */ if (!salt_prefix) { salt_minlen = methods[0].minlen; salt_maxlen = methods[0].maxlen; salt_prefix = methods[0].prefix; } if (streq(salt_prefix, "$2a$") || streq(salt_prefix, "$2y$")) { /* OpenBSD Blowfish and derivatives */ if (rounds <= 5) rounds = 5; /* actually for 2a/2y it is the logarithm of the number of rounds */ snprintf(rounds_str, sizeof(rounds_str), "%02u$", rounds); } else if (rounds_support && rounds) snprintf(rounds_str, sizeof(rounds_str), "rounds=%u$", rounds); else rounds_str[0] = '\0'; if (salt_arg) { unsigned int c = strlen(salt_arg); if (c < salt_minlen || c > salt_maxlen) { if (salt_minlen == salt_maxlen) fprintf(stderr, ngettext( "Wrong salt length: %d byte when %d expected.\n", "Wrong salt length: %d bytes when %d expected.\n", c), c, salt_maxlen); else fprintf(stderr, ngettext( "Wrong salt length: %d byte when %d <= n <= %d" " expected.\n", "Wrong salt length: %d bytes when %d <= n <= %d" " expected.\n", c), c, salt_minlen, salt_maxlen); exit(1); } while (c-- > 0) { if (strchr(valid_salts, salt_arg[c]) == NULL) { fprintf(stderr, _("Illegal salt character '%c'.\n"), salt_arg[c]); exit(1); } } salt = NOFAIL(malloc(strlen(salt_prefix) + strlen(rounds_str) + strlen(salt_arg) + 1)); *salt = '\0'; strcat(salt, salt_prefix); strcat(salt, rounds_str); strcat(salt, salt_arg); } else { #ifdef HAVE_SOLARIS_CRYPT_GENSALT salt = crypt_gensalt(salt_prefix, NULL); if (!salt) perror("crypt_gensalt"); #elif defined HAVE_LINUX_CRYPT_GENSALT void *entropy = get_random_bytes(64); salt = crypt_gensalt(salt_prefix, rounds, entropy, 64); if (!salt) { fprintf(stderr, "crypt_gensalt failed.\n"); exit(2); } free(entropy); #else unsigned int salt_len = salt_maxlen; if (salt_minlen != salt_maxlen) { /* salt length can vary */ srand(time(NULL) + getpid()); salt_len = rand() % (salt_maxlen - salt_minlen + 1) + salt_minlen; } salt = NOFAIL(malloc(strlen(salt_prefix) + strlen(rounds_str) + salt_len + 1)); *salt = '\0'; strcat(salt, salt_prefix); strcat(salt, rounds_str); generate_salt(salt + strlen(salt), salt_len); #endif } if (password) { } else if (password_fd != -1) { FILE *fp; char *p; if (isatty(password_fd)) fprintf(stderr, _("Password: "******"r"); if (!fp) { perror("fdopen"); exit(2); } if (!fgets(password, 128, fp)) { perror("fgets"); exit(2); } p = strpbrk(password, "\n\r"); if (p) *p = '\0'; } else { password = getpass(_("Password: "******"getpass"); exit(2); } } { const char *result; result = crypt(password, salt); /* xcrypt returns "*0" on errors */ if (!result || result[0] == '*') { fprintf(stderr, "crypt failed.\n"); exit(2); } /* yes, using strlen(salt_prefix) on salt. It's not * documented whether crypt_gensalt may change the prefix */ if (!strneq(result, salt, strlen(salt_prefix))) { fprintf(stderr, _("Method not supported by crypt(3).\n")); exit(2); } printf("%s\n", result); } exit(0); }
int reauthorize_prepare (const char *user, const char *password, long keyring, long *out_key) { struct crypt_data *cd = NULL; key_serial_t key; const char *secret; char *salt = NULL; ssize_t salt_len; char *name = NULL; key_perm_t perm; int ret; if (password == NULL) { debug ("no password available for user %s", user); return 0; } /* The salt already contains algorithm prefix and suffix */ ret = generate_salt (&salt); if (ret < 0) { message ("couldn't generate crypt salt: %m"); goto out; } cd = calloc (1, sizeof (struct crypt_data)); if (!cd) { message ("couldn't allocate crypt data"); ret = -ENOMEM; goto out; } secret = crypt_r (password, salt, cd); if (!secret) { ret = -errno; message ("couldn't crypt reauthorize secret: %m"); goto out; } /* * Double check that our assumptions about crypt() work * as expected. We're later going to be sending away the * salt as a challenge, so guarantee that it works. */ salt_len = parse_salt (secret); if (salt_len != strlen (salt) || memcmp (secret, salt, salt_len) != 0) { ret = -EINVAL; message ("got invalid result from crypt"); goto out; } if (asprintf (&name, "reauthorize/secret/%s", user) < 0) { ret = -ENOMEM; message ("couldn't allocate keyring name"); goto out; } /* * Don't put our secret into the session keyring until the permissions * are strong enough. Since we want that to be atomic, first store in * our thread keyring, and then link below. */ if (keyring == 0) keyring = KEY_SPEC_SESSION_KEYRING; key = add_key ("user", name, "xxx", 3, keyring); if (key < 0) { ret = -errno; message ("couldn't create key in kernel session keyring: %s: %m", name); goto out; } /* Set permissions, and double check that what we expect happened */ perm = KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE | KEY_USR_SEARCH | KEY_USR_LINK; if (keyctl_setperm (key, perm) < 0) { ret = -errno; message ("couldn't set permissions on kernel key: %s: %m", name); goto out; } if (keyctl_update (key, secret, strlen (secret))) { ret = -errno; message ("couldn't update secret reauthorize key in kernel keyring: %s: %m", name); goto out; } debug ("placed secret in kernel session keyring"); *out_key = key; ret = 0; out: secfree (cd, sizeof (struct crypt_data)); free (name); free (salt); return ret; }
int authenticate(char **p) { FILE *f_key, *f_salt; unsigned char key[AES256_KEY_SIZE], key_stored[AES256_KEY_SIZE]; unsigned char salt[SHA256_SALT_SIZE]; char *password, key_fn[BUFFER_SIZE], salt_fn[BUFFER_SIZE]; int match, i, e, kl, sl, first; first = 0; snprintf(key_fn, BUFFER_SIZE, "%s/key", fn_dir); snprintf(salt_fn, BUFFER_SIZE, "%s/salt", fn_dir); f_key = fopen(key_fn, "rb"); f_salt = fopen(salt_fn, "rb"); first += (f_key == NULL) + (f_salt == NULL); /* A password and salt are stored, so we authenticate */ if(!first) { /* Read salt and stored key for verification */ kl = fread(key_stored, 1, AES256_KEY_SIZE, f_key); sl = fread(salt, 1, SHA256_SALT_SIZE, f_salt); fclose(f_key); fclose(f_salt); /* Check password */ password = getpassword("Password: "******"gcry error: %d\n", e); for(i = 0, match = 1; i < AES256_KEY_SIZE; ++i) match = match && (key[i] == key_stored[i]); if(match) printf("Authentication OK, welcome\n"); else { printf("Authentication failure\n"); return 1; } /* One or both are missing, so we set up new ones */ } else { char *cp; int match = 0; if(f_key) fclose(f_key); if(f_salt) fclose(f_salt); /* Prompt for new password */ printf("No password set, prompting new one.\n"); do { password = getpassword("Password: "******"Confirm password: "******"Passwords do not match, try again.\n"); } while(!match); memset(cp, 0, BUFFER_SIZE); free(cp); /* Generate a salt and key from it */ generate_salt(salt); gcry_kdf_derive(password, strlen(password), GCRY_KDF_PBKDF2, GCRY_MD_SHA256, salt, SHA256_SALT_SIZE, SHA256_ITERATIONS, AES256_KEY_SIZE, key); f_key = fopen(key_fn, "wb"); fwrite(key, 1, AES256_KEY_SIZE, f_key); fclose(f_key); f_salt = fopen(salt_fn, "wb"); fwrite(salt, 1, SHA256_SALT_SIZE, f_salt); fclose(f_salt); printf("New key stored.\n"); } /* Allow the password to be passed back to the caller */ *p = password; return 0; }
/* * Make a password record from the given information. A zero return * indicates success; on failure, ctx->errstr points to the error message. */ int mkhash(struct passwd_ctx *ctx) { char *pw; char pwin[MAX_STRING_LEN]; char salt[16]; apr_status_t rv; int ret = 0; #if CRYPT_ALGO_SUPPORTED char *cbuf; #endif if (ctx->cost != 0 && ctx->alg != ALG_BCRYPT) { apr_file_printf(errfile, "Warning: Ignoring -C argument for this algorithm." NL); } if (ctx->passwd != NULL) { pw = ctx->passwd; } else { if ((ret = get_password(ctx)) != 0) return ret; pw = pwin; } switch (ctx->alg) { case ALG_APSHA: /* XXX out >= 28 + strlen(sha1) chars - fixed len SHA */ apr_sha1_base64(pw, strlen(pw), ctx->out); break; case ALG_APMD5: ret = generate_salt(salt, 8, &ctx->errstr, ctx->pool); if (ret != 0) break; rv = apr_md5_encode(pw, salt, ctx->out, ctx->out_len); if (rv != APR_SUCCESS) { ctx->errstr = apr_psprintf(ctx->pool, "could not encode password: %pm", &rv); ret = ERR_GENERAL; } break; case ALG_PLAIN: /* XXX this len limitation is not in sync with any HTTPd len. */ apr_cpystrn(ctx->out, pw, ctx->out_len); break; #if CRYPT_ALGO_SUPPORTED case ALG_CRYPT: ret = generate_salt(salt, 8, &ctx->errstr, ctx->pool); if (ret != 0) break; cbuf = crypt(pw, salt); if (cbuf == NULL) { rv = APR_FROM_OS_ERROR(errno); ctx->errstr = apr_psprintf(ctx->pool, "crypt() failed: %pm", &rv); ret = ERR_PWMISMATCH; break; } apr_cpystrn(ctx->out, cbuf, ctx->out_len - 1); if (strlen(pw) > 8) { char *truncpw = strdup(pw); truncpw[8] = '\0'; if (!strcmp(ctx->out, crypt(truncpw, salt))) { apr_file_printf(errfile, "Warning: Password truncated to 8 " "characters by CRYPT algorithm." NL); } memset(truncpw, '\0', strlen(pw)); free(truncpw); } break; #endif /* CRYPT_ALGO_SUPPORTED */ #if BCRYPT_ALGO_SUPPORTED case ALG_BCRYPT: rv = apr_generate_random_bytes((unsigned char*)salt, 16); if (rv != APR_SUCCESS) { ctx->errstr = apr_psprintf(ctx->pool, "Unable to generate random " "bytes: %pm", &rv); ret = ERR_RANDOM; break; } if (ctx->cost == 0) ctx->cost = BCRYPT_DEFAULT_COST; rv = apr_bcrypt_encode(pw, ctx->cost, (unsigned char*)salt, 16, ctx->out, ctx->out_len); if (rv != APR_SUCCESS) { ctx->errstr = apr_psprintf(ctx->pool, "Unable to encode with " "bcrypt: %pm", &rv); ret = ERR_PWMISMATCH; break; } break; #endif /* BCRYPT_ALGO_SUPPORTED */ default: apr_file_printf(errfile, "mkhash(): BUG: invalid algorithm %d", ctx->alg); abort(); } memset(pw, '\0', strlen(pw)); return ret; }
/* * Make a password record from the given information. A zero return * indicates success; failure means that the output buffer contains an * error message instead. */ static int mkrecord(char *user, char *record, apr_size_t rlen, char *passwd, int alg) { char *pw; char cpw[120]; char pwin[MAX_STRING_LEN]; char pwv[MAX_STRING_LEN]; char salt[9]; apr_size_t bufsize; if (passwd != NULL) { pw = passwd; } else { bufsize = sizeof(pwin); if (apr_password_get("New password: "******"password too long (>%" APR_SIZE_T_FMT ")", sizeof(pwin) - 1); return ERR_OVERFLOW; } bufsize = sizeof(pwv); apr_password_get("Re-type new password: "******"password verification error", (rlen - 1)); return ERR_PWMISMATCH; } pw = pwin; memset(pwv, '\0', sizeof(pwin)); } switch (alg) { case ALG_APSHA: /* XXX cpw >= 28 + strlen(sha1) chars - fixed len SHA */ apr_sha1_base64(pw,strlen(pw),cpw); break; case ALG_APMD5: if (seed_rand()) { break; } generate_salt(&salt[0], 8); salt[8] = '\0'; apr_md5_encode((const char *)pw, (const char *)salt, cpw, sizeof(cpw)); break; case ALG_PLAIN: /* XXX this len limitation is not in sync with any HTTPd len. */ apr_cpystrn(cpw,pw,sizeof(cpw)); break; #if (!(defined(WIN32) || defined(NETWARE))) case ALG_CRYPT: default: if (seed_rand()) { break; } to64(&salt[0], rand(), 8); salt[8] = '\0'; apr_cpystrn(cpw, crypt(pw, salt), sizeof(cpw) - 1); if (strlen(pw) > 8) { char *truncpw = strdup(pw); truncpw[8] = '\0'; if (!strcmp(cpw, crypt(truncpw, salt))) { apr_file_printf(errfile, "Warning: Password truncated to 8 characters " "by CRYPT algorithm." NL); } free(truncpw); } break; #endif } memset(pw, '\0', strlen(pw)); /* * Check to see if the buffer is large enough to hold the username, * hash, and delimiters. */ if ((strlen(user) + 1 + strlen(cpw)) > (rlen - 1)) { apr_cpystrn(record, "resultant record too long", (rlen - 1)); return ERR_OVERFLOW; } strcpy(record, user); strcat(record, ":"); strcat(record, cpw); strcat(record, "\n"); return 0; }
static int rehash_verity(const int meta_version, const int dm_verity_version, const char * data_device, const size_t block_size) { #if 0 int r = -1; char *table, *salt = NULL; salt = malloc(32); /* biggest length */ if (NULL == salt) { fprintf(stderr, "Failed to malloc mem for salt\n"); return -1; } #endif int ret = 0; uint64_t part_size; if(ext4_part_size(TARGET_DEV, &part_size)) { printf("failed to get part size.\n"); return -1; } const char * tmp_hash_file = TMP_HASH_FILE; const char * tmp_hash_table = TMP_HASH_TABLE; //unlink(tmp_hash_file); //unlink(tmp_hash_table); const char * hash_name = HASH_NAME; int i; char * table = NULL, *p; const long data_blocks = part_size / DMVERITY_BLOCK_SIZE; #ifdef USE_SHA256 const int digest_size = 32;//sha256 #elif USE_SHA1 const int digest_size = 20;//sha1 #else const int digest_size = 16;//md5 #endif char salt[digest_size]; char root_hash[digest_size]; const loff_t hash_start = (part_size + DMVERITY_META_SIZE)/DMVERITY_BLOCK_SIZE; const loff_t hash_position = DMVERITY_META_SIZE/DMVERITY_BLOCK_SIZE; struct verity_meta_header meta_header; FILE * fp; //0.1 generate random salt /* generate_salt(salt); */ if (generate_salt(salt, digest_size) != digest_size) { printf("Error generating random salt.\n"); // how to handle it better? now it will use whatever compiler gives: all 0's } // 1. generate hash, table and write to a tmp hash file if(VERITY_create_hash(dm_verity_version, \ hash_name, \ TMP_HASH_FILE, \ data_device, \ block_size, \ block_size, \ data_blocks, \ hash_position, \ (unsigned char *)root_hash, \ digest_size, \ (const unsigned char *)salt, \ digest_size)) { printf("failed to create hash tree\n"); ret = -1; goto rehash_out; } int table_size = nDigits(dm_verity_version) + 1 + strlen(TARGET_DEV) + 1 + strlen(TARGET_DEV) + 1 + nDigits(DMVERITY_BLOCK_SIZE) + 1 + nDigits(DMVERITY_BLOCK_SIZE) + 1 + nDigits(data_blocks) + 1 + nDigits(hash_start) + 1 + strlen(hash_name) + 1 + digest_size * 2 + 1 + digest_size * 2 + 1; table = malloc(table_size); if(NULL == table){ printf("malloc failed\n"); ret = -1; goto rehash_out; } table[table_size-1] = 0; i = sprintf(table, "%d %s %s %lld %lld %lld %lld %s ", dm_verity_version, TARGET_DEV, TARGET_DEV, (long long int) DMVERITY_BLOCK_SIZE, (long long int) DMVERITY_BLOCK_SIZE, (long long int) data_blocks, (long long int) hash_start, hash_name); if(i <= 0){ printf("sprintf error"); free(table); ret = -1; goto rehash_out; } //printf("Table: %s\n", table); p = table + i; bytes_to_hex(root_hash, p, digest_size); p += digest_size * 2; p += sprintf(p, " "); bytes_to_hex(salt, p, digest_size); printf("table: %s", table); // 2.1 generate meta_header meta_header.magic_number = VERITY_METADATA_MAGIC_NUMBER; meta_header.protocol_version = 0; meta_header.table_length = strlen(table);//not including trailing NULL memset(&meta_header.signature, 0, sizeof(meta_header.signature)); //tmp_hash_file it should have been created by generate_dm_verity_hash already. // 2.2 write table and meta_header to tmp hash file fp = fopen(tmp_hash_file, "r+"); if (NULL == fp) { printf("failed to open temp file\n"); ret = -1; goto rehash_out; } if(1 != fwrite(&meta_header, sizeof(struct verity_meta_header), 1, fp)){ printf("failed to write temp file\n"); fclose(fp); ret = -1; goto rehash_out; } printf("write meta_header %d\n", sizeof(struct verity_meta_header)); if(1 != fwrite(table, meta_header.table_length+1, 1, fp)){ printf("failed to write temp file\n"); fclose(fp); ret = -1; goto rehash_out; } printf("write table %d\n", meta_header.table_length+1); fflush(fp); fsync(fileno(fp)); fclose(fp); // 2.3 write table to tmp hash meta table file fp = fopen(tmp_hash_table, "w"); if (NULL == fp) { printf("failed to open temp meta table file\n"); ret = -1; goto rehash_out; } if(1 != fwrite(table, meta_header.table_length+1, 1, fp)){ printf("failed to write temp meta table file\n"); fclose(fp); ret = -1; goto rehash_out; } printf("write table %d\n", meta_header.table_length+1); fflush(fp); fsync(fileno(fp)); fclose(fp); // 3. write tmp hash file to the /system (not signed) /* if(file_to_device(tmp_hash_file, TARGET_DEV, 1024*1024, part_size)){ printf("failed to write hash 001\n"); goto rehash_out; } */ rehash_out: //unlink(tmp_hash_file); if(table) free(table); return ret; }
json_t *broker_handshake_handle_conn(Broker *broker, const char *dsId, const char *token, json_t *handshake) { if (dslink_map_contains(&broker->client_connecting, (void *) dsId)) { ref_t *ref = dslink_map_remove_get(&broker->client_connecting, (void *) dsId); RemoteDSLink *link = ref->data; dslink_map_remove(&broker->client_connecting, (void *) link->name); broker_remote_dslink_free(link); dslink_free(link); dslink_decref(ref); } RemoteDSLink *link = dslink_calloc(1, sizeof(RemoteDSLink)); json_t *resp = json_object(); if (!(link && resp)) { goto fail; } if (broker_remote_dslink_init(link) != 0) { goto fail; } link->broker = broker; link->auth = dslink_calloc(1, sizeof(RemoteAuth)); if (!link->auth) { goto fail; } if (dslink_handshake_generate_key_pair(&link->auth->tempKey) != 0) { log_err("Failed to create temporary key for DSLink\n"); goto fail; } { json_t *jsonPubKey = json_object_get(handshake, "publicKey"); if (!jsonPubKey) { goto fail; } const char *tmp = json_string_value(jsonPubKey); if (!tmp) { goto fail; } tmp = dslink_strdup(tmp); if (!tmp) { goto fail; } link->auth->pubKey = tmp; } char tempKey[90]; size_t tempKeyLen = 0; if (dslink_handshake_encode_pub_key(&link->auth->tempKey, tempKey, sizeof(tempKey), &tempKeyLen) != 0) { goto fail; } if (generate_salt((unsigned char *) link->auth->salt, sizeof(link->auth->salt)) != 0) { goto fail; } json_object_set_new_nocheck(resp, "wsUri", json_string_nocheck("/ws")); json_object_set_new_nocheck(resp, "tempKey", json_string_nocheck(tempKey)); json_object_set_new_nocheck(resp, "salt", json_string_nocheck(link->auth->salt)); if (json_boolean_value(json_object_get(handshake, "isResponder"))) { link->isResponder = 1; } if (json_boolean_value(json_object_get(handshake, "isRequester"))) { link->isRequester = 1; } json_t *linkData = json_object_get(handshake, "linkData"); if (json_is_object(linkData)) { json_incref(linkData); link->linkData = linkData; } { char buf[512] = {0}; snprintf(buf, sizeof(buf), "/downstream/"); char *name = buf + sizeof("/downstream/")-1; size_t dsIdLen = strlen(dsId); if (dsIdLen < 44) { goto fail; } size_t nameLen = dsIdLen - 43; if (dsId[nameLen - 1] == '-') { nameLen--; } int nodeExists = 0; // find a valid name from broker->client_names memcpy(name, dsId, nameLen); while (1) { ref_t *ref = dslink_map_get(&broker->client_connecting, name); if (ref) { RemoteDSLink *l = ref->data; if (l && l->dsId && strcmp(l->dsId->data, dsId) == 0) { dslink_map_remove(&broker->client_connecting, name); broker_remote_dslink_free(l); break; } else { name[nameLen] = dsId[nameLen]; nameLen++; } } ref = dslink_map_get(broker->downstream->children, (void *) name); if (ref == NULL) { break; } if (!((DownstreamNode *) ref->data)->dsId || strcmp(dsId, ((DownstreamNode *) ref->data)->dsId->data) == 0) { nodeExists = 1; break; } name[nameLen] = dsId[nameLen]; nameLen++; } if (!nodeExists && broker_enable_token) { if (!token) { log_err("Failed to connet, need token\n"); goto fail; } BrokerNode* tokenNode = get_token_node(token, dsId); if (tokenNode) { DownstreamNode *node = broker_init_downstream_node(broker->downstream, name); if (json_is_true(json_object_get(node->meta, "$$managed"))) { json_object_set_new_nocheck(node->meta, "$$token", json_string_nocheck(tokenNode->name)); } node->dsId = dslink_str_ref(dsId); if (broker->downstream->list_stream) { update_list_child(broker->downstream, broker->downstream->list_stream, link->name); } json_t *group = json_object_get(tokenNode->meta, "$$group"); if (json_is_string(group)) { json_object_set_nocheck(node->meta, "$$group", group); } token_used(tokenNode); broker_downstream_nodes_changed(broker); } else { log_err("Invalid token: %s\n", token); goto fail; } } json_object_set_new_nocheck(resp, "path", json_string_nocheck(buf)); link->path = dslink_strdup(buf); if (!link->path) { goto fail; } link->name = link->path + sizeof("/downstream/") - 1; // add to connecting map with the name if (dslink_map_set(&broker->client_connecting, dslink_ref((void *) link->name, NULL), dslink_ref(link, NULL)) != 0) { dslink_free((void *) link->path); goto fail; } } { ref_t *tmp = dslink_ref(dslink_strdup(dsId), dslink_free); if (!tmp) { goto fail; } // add to connecting map with dsId if (dslink_map_set(&broker->client_connecting, tmp, dslink_ref(link, NULL)) != 0) { dslink_free(tmp); goto fail; } } return resp; fail: if (link) { broker_remote_dslink_free(link); dslink_free((void *) link->path); dslink_free(link); } DSLINK_CHECKED_EXEC(json_decref, resp); return NULL; }