int shfs_ref_get(shfs_ino_t *file, shfs_t **ref_fs_p, shfs_ino_t **ref_p) { shfs_ino_t *ref; shfs_ino_t *parent; shpeer_t *peer; shfs_t *fs; shkey_t *hier; shbuf_t *buff; char path[SHFS_PATH_MAX]; int hier_cnt; int err; int i; *ref_p = NULL; *ref_fs_p = NULL; if (!file || !file->tree) return (SHERR_INVAL); buff = shbuf_init(); err = _shfs_ref_raw_read(file, buff); if (err) return (err); peer = (shpeer_t *)shbuf_data(buff); hier = (shkey_t *)(shbuf_data(buff) + sizeof(shpeer_t)); fs = shfs_init(peer); if (!fs) return (SHERR_IO); memset(path, 0, sizeof(path)); strcpy(path, "/"); ref = fs->fsbase_ino; for (i = SHFS_MAX_REFERENCE_HIERARCHY - 1; i >= 0; i--) { if (shkey_cmp(&hier[i], ashkey_blank())) continue; if (shkey_cmp(&hier[i], shfs_token(file->tree->fsbase_ino))) continue; ref = shfs_inode_load(ref, &hier[i]); if (!ref) { shfs_free(&fs); return (SHERR_NOENT); } if (shfs_type(ref) == SHINODE_DIRECTORY) strncat(path, "/", SHFS_PATH_MAX - strlen(path) - 1); strncat(path, shfs_filename(ref), SHFS_PATH_MAX - strlen(path) - 1); } shbuf_free(&buff); *ref_p = ref; *ref_fs_p = fs; return (0); }
/** reference a revision by name */ int shfs_rev_ref(shfs_ino_t *file, char *group, char *name, shfs_ino_t *rev) { shfs_ino_t *branch; shfs_ino_t *ref; shkey_t *ref_key; char buf[SHFS_PATH_MAX]; int err; if (!rev) { return (SHERR_INVAL); } if (shfs_type(rev) != SHINODE_REVISION) return (SHERR_INVAL); ref_key = shkey_hexgen(shfs_filename(rev)); if (!ref_key) return (SHERR_IO); if (shkey_cmp(ref_key, ashkey_blank())) { /* not a revision (filename has no hex key) */ shkey_free(&ref_key); return (SHERR_INVAL); } memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf)-1, "%s/%s", group, name); err = shfs_obj_set(file, buf, ref_key); shkey_free(&ref_key); if (err) return (err); return (0); }
/** * @see shsig_shr_verify() */ static int _shcert_sign_verify_shr(shcert_t *cert, shcert_t *parent) { shkey_t *key; unsigned char *enc_data; size_t enc_len; int err; if (!parent) return (SHERR_INVAL); err = shencode((char *)&parent->cert_sub.ent_sig.sig_key, sizeof(shkey_t), &enc_data, &enc_len, &parent->cert_iss.ent_sig.sig_key); if (err) return (err); key = shkey_bin(enc_data, enc_len); free(enc_data); if (!shkey_cmp(key, &cert->cert_sub.ent_sig.sig_key)) { /* encrypted key is not validated. */ shkey_free(&key); return (SHERR_KEYREJECTED); } shkey_free(&key); return (0); }
int shpam_shadow_setpass(shfs_ino_t *file, shseed_t *seed, shkey_t *sess_key) { shadow_t *ent; shadow_t save; shkey_t *seed_key; int err; seed_key = shkey_bin((char *)&seed->seed_uid, sizeof(seed->seed_uid)); ent = shpam_shadow(file, seed_key); shkey_free(&seed_key); if (!ent) return (SHERR_NOENT); memcpy(&save, ent, sizeof(shadow_t)); if (shtime64() >= save.sh_expire) return (SHERR_KEYEXPIRED); if (!shkey_cmp(&save.sh_sess, sess_key)) return (SHERR_KEYREJECTED); seed_key = shkey_bin((char *)&seed->seed_uid, sizeof(seed->seed_uid)); err = shpam_shadow_session_expire(file, seed_key, sess_key); shkey_free(&seed_key); if (err) return (err); err = shpam_shadow_pass_append(file, seed); if (err) return (err); return (0); }
int shpam_shadow_session_set(shfs_ino_t *file, uint64_t uid, shkey_t *id_key, uint64_t sess_stamp, shkey_t *sess_key) { shadow_t shadow; shseed_t save; int err; err = shpam_pshadow_load(file, uid, &save); if (err) return (err); err = shpam_sess_verify(sess_key, &save.seed_key, sess_stamp, id_key); if (err) return (err); err = shpam_shadow_load(file, uid, &shadow); if (err) return (err); if (!shkey_cmp(id_key, &shadow.sh_id)) return (SHERR_INVAL); shadow.sh_expire = sess_stamp; memcpy(&shadow.sh_sess, sess_key, sizeof(shadow.sh_sess)); err = shpam_shadow_store(file, &shadow); if (err) return (err); return (0); }
int shpam_pshadow_set(shfs_ino_t *file, shseed_t *seed, shkey_t *sess_key) { shadow_t save; int err; err = shpam_shadow_load(file, seed->seed_uid, &save); if (err) return (err); /* validate session key */ if (shtime_after(shtime(), save.sh_expire)) return (SHERR_KEYEXPIRED); if (!shkey_cmp(&save.sh_sess, sess_key)) return (SHERR_KEYREJECTED); err = shpam_shadow_session_expire(file, seed->seed_uid, sess_key); if (err) return (err); err = shpam_pshadow_store(file, seed); if (err) return (err); return (0); }
static int _shcert_sign_verify_ecdsa(shcert_t *cert, shcert_t *parent) { shkey_t *pub_key; char *hex_data; unsigned char data[256]; int data_len; int err; if (parent) { if (!shkey_cmp(shcert_sub_sig(parent), shcert_iss_sig(cert))) { return (SHERR_INVAL); } } hex_data = shkey_hex(&cert->cert_iss.ent_sig.sig_key); data_len = strlen(hex_data) / 2; if (!data_len) { return (SHERR_INVAL); } memset(data, 0, sizeof(data)); hex2bin(data, hex_data, data_len); pub_key = &cert->cert_sub.ent_sig.sig_key; err = shecdsa_verify(pub_key, cert->cert_sub.ent_sig.key.ecdsa.sig_r, cert->cert_sub.ent_sig.key.ecdsa.sig_s, data, data_len); if (err) return (err); return (0); }
int shpam_shadow_remove(shfs_ino_t *file, uint64_t uid, shkey_t *sess_key) { shadow_t *ent; shadow_t save; shkey_t *key; int err; if (!sess_key) return (SHERR_NOKEY); err = shpam_shadow_load(file, uid, &save); if (err) { return (err); } if (shtime_after(shtime(), save.sh_expire)) return (SHERR_KEYEXPIRED); if (!shkey_cmp(&save.sh_sess, sess_key)) return (SHERR_KEYREJECTED); key = shkey_bin((char *)&uid, sizeof(uid)); err = shfs_cred_remove(file, key); shkey_free(&key); if (err) { return (err); } return (0); }
int txop_contract_confirm(shpeer_t *peer, tx_contract_t *contract) { shtime_t now; shkey_t *key; int sig_ok; if (0 != strcmp(contract->con_cur, COIN_USDE) && 0 != strcmp(contract->con_cur, COIN_GMC) && 0 != strcmp(contract->con_cur, COIN_SYS)) return (SHERR_INVAL); now = shtime(); if (shtime_before(shtime(), contract->con_birth) || shtime_before(shtime(), contract->con_stamp) || shtime_after(contract->con_birth, contract->con_stamp)) return (SHERR_TIME); key = shkey_hexgen(contract->con_key + 8); if (!key) return (SHERR_NOKEY); sig_ok = shkey_cmp(key, &contract->con_sig); shkey_free(&key); if (!sig_ok) return (SHERR_KEYREJECTED); return (0); }
/** * @returns An allocated parent transaction or NULL. */ tx_t *get_tx_parent(tx_t *tx) { tx_t *p_tx; if (0 == shkey_cmp(&tx->tx_pkey, ashkey_blank())) return (NULL); return ((tx_t *)pstore_load(tx->tx_ptype, shkey_hex(&tx->tx_pkey))); }
/** Determine whether the appropriate context is availale. */ int txward_context_confirm(tx_ward_t *ward, tx_context_t *ctx) { int err; if (!shkey_cmp(&ward->ward_ref, &ctx->ctx_ref)) return (SHERR_INVAL); err = shkey_verify(&ward->ward_sig, shkey_crc(&ctx->ctx_ref), &ctx->ctx_sig, ward->ward_tx.tx_stamp); if (err) return (err); return (0); }
void info_table_add_key(info_table_t *table, char *col_name, shkey_t *key) { int idx; if (!key || shkey_cmp(ashkey_blank(), key)) return; if (!(run_flags & PFLAG_VERBOSE)) return; idx = info_table_column(table, col_name); if (idx != -1) table->row->col[idx] = strdup(shkey_print(key)); }
shfs_ino_t *shfs_rev_get(shfs_ino_t *repo, shkey_t *rev_key) { shfs_ino_t *rev; if (shfs_type(repo) == SHINODE_FILE) repo = shfs_inode(repo, NULL, SHINODE_REPOSITORY); if (shfs_type(repo) != SHINODE_REPOSITORY) return (NULL); if (shkey_cmp(rev_key, ashkey_blank())) return (NULL); return (shfs_inode(repo, (char *)shkey_hex(rev_key), SHINODE_REVISION)); }
shadow_t *shpam_shadow(shfs_ino_t *file, shkey_t *seed_key) { static shadow_t ret_shadow; int err; memset(&ret_shadow, 0, sizeof(ret_shadow)); err = shfs_cred_load(file, seed_key, (unsigned char *)&ret_shadow, sizeof(ret_shadow)); if (err) return (NULL); if (!shkey_cmp(seed_key, &ret_shadow.sh_seed)) return (NULL); return (&ret_shadow); }
int shpam_shadow_verify(shfs_ino_t *file, shkey_t *seed_key) { shadow_t shadow; int err; memset(&shadow, 0, sizeof(shadow)); err = shfs_cred_load(file, seed_key, (unsigned char *)&shadow, sizeof(shadow)); if (err) return (SHERR_NOKEY); if (!shkey_cmp(seed_key, &shadow.sh_seed)) return (SHERR_ACCESS); return (0); }
int txop_trust_init(shpeer_t *cli_peer, tx_trust_t *trust) { shkey_t *sig_key; uint64_t crc; int err; if (!trust) return (SHERR_INVAL); if (shkey_cmp(&trust->trust_ctx, ashkey_blank())) memcpy(&trust->trust_ctx, ashkey_uniq(), sizeof(trust->trust_ctx)); tx_sign(trust, &trust->trust_sig, &trust->trust_ctx); return (0); }
int shkey_verify(shkey_t *sig, uint64_t crc, shkey_t *key, shtime_t stamp) { shkey_t *sha_key; char *ptr; int valid; sha_key = shkey_cert(key, crc, stamp); valid = shkey_cmp(sha_key, sig); shkey_free(&sha_key); if (!valid) return (SHERR_INVAL); return (0); }
int update_sexe_userdata(sexe_t *S) { SHFL *fl; shjson_t *udata; shfs_t *fs; shbuf_t *buff; shkey_t *k; char path[PATH_MAX+1]; char *str; int err; k = &S->pname; if (shkey_cmp(k, ashkey_blank())) { fprintf(stderr, "DEBUG: update_sexe_userdata: no app key\n"); return (0); /* blank */ } sprintf(path, "/sys/data/sexe/%s", shkey_hex(k)); lua_getglobal(S, "userdata"); udata = sexe_table_get(S); if (!udata) { fprintf(stderr, "DEBUG: update_sexe_userdata: no global 'userdata' variable.\n"); return (SHERR_INVAL); } str = shjson_print(udata); if (!str) { fprintf(stderr, "DEBUG: update_sexe_userdata: error encoding JSON.\n"); return (SHERR_INVAL); } shjson_free(&udata); buff = shbuf_init(); shbuf_catstr(buff, str); free(str); fs = shfs_init(NULL); fl = shfs_file_find(fs, path); err = shfs_write(fl, buff); shbuf_free(&buff); shfs_free(&fs); return (err); }
/** Associated a particular context with releasing a ward. */ void txward_context_sign(tx_ward_t *ward, tx_context_t *ctx) { shkey_t *sig_key; if (!ward || !ctx) return; if (!shkey_cmp(&ward->ward_ref, &ctx->ctx_ref)) return (SHERR_INVAL); if (ward->ward_tx.tx_stamp == SHTIME_UNDEFINED) ward->ward_tx.tx_stamp = shtime(); sig_key = shkey_cert(&ctx->ctx_sig, shkey_crc(&ctx->ctx_ref), ward->ward_tx.tx_stamp); memcpy(&ward->ward_sig, sig_key, sizeof(ward->ward_sig)); shkey_free(&sig_key); }
int shpam_shadow_delete(shfs_ino_t *file, char *acc_name, shkey_t *sess_key) { shadow_t *ent; shadow_t save; shkey_t *seed_key; int ret_err; int err; if (!sess_key) return (SHERR_INVAL); seed_key = shpam_seed(acc_name); ent = shpam_shadow(file, seed_key); shkey_free(&seed_key); if (!ent) return (SHERR_NOKEY); memcpy(&save, ent, sizeof(shadow_t)); if (shtime64() >= save.sh_expire) return (SHERR_KEYEXPIRED); if (!shkey_cmp(&save.sh_sess, sess_key)) return (SHERR_KEYREJECTED); if (save.sh_flag & SHPAM_LOCK) return (SHERR_ACCESS); ret_err = 0; err = shfs_cred_remove(file, &save.sh_seed); if (err) ret_err = err; err = shpam_shadow_pass_remove(file, shpam_uid(acc_name)); if (err) ret_err = err; return (ret_err); }
int shpam_shadow_session_expire(shfs_ino_t *file, uint64_t uid, shkey_t *sess_key) { shadow_t *ent; shadow_t save; int err; err = shpam_shadow_load(file, uid, &save); if (err) return (err); if (shtime_after(shtime(), save.sh_expire)) return (SHERR_KEYEXPIRED); if (!shkey_cmp(&save.sh_sess, sess_key)) return (SHERR_KEYREJECTED); save.sh_expire = 0; err = shpam_shadow_store(file, &save); if (err) return (err); return (0); }
int confirm_tx_key(txop_t *op, tx_t *tx) { shkey_t *c_key = &tx->tx_key; shkey_t *key; shbuf_t *buff; tx_t *k_tx; size_t len; int confirm; if (!op || !tx) return (SHERR_INVAL); if (op->op_size == 0) return (0); /* allocate working copy */ len = MAX(sizeof(tx_t), op->op_keylen ? op->op_keylen : op->op_size); buff = shbuf_init(); shbuf_cat(buff, (char *)tx, len); /* blank out tx key */ k_tx = (tx_t *)shbuf_data(buff); memset(&k_tx->tx_key, '\000', sizeof(k_tx->tx_key)); /* verify generated tx key matches. */ key = shkey_bin(shbuf_data(buff), shbuf_size(buff)); confirm = shkey_cmp(c_key, key); shkey_free(&key); shbuf_free(&buff); if (!confirm) { return (SHERR_INVAL); } return (0); }
/** * Generates the working-copy for a particular revision. */ int shfs_rev_read(shfs_ino_t *i_rev, shbuf_t *buff) { shfs_ino_t *repo; shfs_ino_t *file; shfs_ino_t *rev; shbuf_t *delta_buff; shbuf_t *head_buff; shbuf_t *out_buff; int err; if (shfs_type(i_rev) != SHINODE_REVISION) { return (SHERR_INVAL); } repo = shfs_inode_parent(i_rev); if (!repo || shfs_type(repo) != SHINODE_REPOSITORY) return (SHERR_IO); file = shfs_inode_parent(repo); if (!file || shfs_type(file) != SHINODE_FILE) return (SHERR_IO); head_buff = shbuf_init(); err = shfs_rev_ref_read(file, "tag", "BASE", head_buff); if (err) return (err); err = SHERR_NOENT; /* ret'd when no matching revision found */ out_buff = shbuf_init(); delta_buff = shbuf_init(); /* search BASE chain for revision -- applying each revision's patch. */ rev = shfs_rev_tag_resolve(file, "BASE"); while (rev) { if (shkey_cmp(shfs_token(rev), shfs_token(i_rev))) { /* found revision in branch chain. */ shbuf_append(head_buff, buff); err = 0; break; } shbuf_clear(delta_buff); err = shfs_rev_delta_read(rev, delta_buff); if (err) break; /* DEBUG: TODO: merge together deltas to reduce performance over-head */ shbuf_clear(out_buff); err = shpatch(head_buff, delta_buff, out_buff); if (err) break; shbuf_clear(head_buff); shbuf_append(out_buff, head_buff); rev = shfs_rev_prev(rev); } shbuf_free(&head_buff); shbuf_free(&out_buff); shbuf_free(&delta_buff); return (err); }
/** * @see shsig_shr_sign() */ int shcert_sign(shcert_t *cert, shcert_t *parent) { shkey_t *key; unsigned char *enc_data; size_t enc_len; int err; if (!parent) return (SHERR_INVAL); if (!(parent->cert_flag & SHCERT_CERT_SIGN)) { /* parent certificate lacks ability to sign. */ return (SHERR_INVAL); } /* assign issuer's 128-bit serial number (regardless of algorythm) */ memcpy(cert->cert_iss.ent_ser, parent->cert_sub.ent_ser, 16); if (cert->cert_sub.ent_sig.sig_key.alg == SHKEY_ALG_ECDSA) { shkey_t *pub_key = &cert->cert_sub.ent_sig.sig_key; shkey_t *priv_key; shkey_t *seed_key; shpeer_t *peer; char sig_r[256]; char sig_s[256]; char *hex_data; unsigned char data[256]; int data_len; /* fill in parent signature */ memcpy(&cert->cert_iss.ent_sig, &parent->cert_sub.ent_sig, sizeof(shsig_t)); peer = shpeer_init(NULL, NULL); seed_key = shpeer_kpriv(peer); priv_key = shecdsa_key_priv(shkey_hex(seed_key)); shpeer_free(&peer); pub_key = shecdsa_key_pub(priv_key); memcpy(&cert->cert_sub.ent_sig.sig_key, pub_key, sizeof(shkey_t)); if ((parent->cert_flag & SHCERT_CERT_NONREPUDIATION)) { /* must be derived from owner to preserve authenticy. */ if (!shkey_cmp(&cert->cert_sub.ent_sig.sig_key, &cert->cert_iss.ent_sig.sig_key)) { return (SHERR_ACCESS); } } hex_data = shkey_hex(&cert->cert_iss.ent_sig.sig_key); data_len = strlen(hex_data) / 2; memset(data, 0, sizeof(data)); hex2bin(data, hex_data, data_len); shecdsa_sign(priv_key, sig_r, sig_s, data, data_len); strcpy(cert->cert_sub.ent_sig.key.ecdsa.sig_r, sig_r); strcpy(cert->cert_sub.ent_sig.key.ecdsa.sig_s, sig_s); cert->cert_sub.ent_len = data_len; shkey_free(&pub_key); shkey_free(&priv_key); } else { err = shencode((char *)&parent->cert_sub.ent_sig.sig_key, sizeof(shkey_t), &enc_data, &enc_len, &parent->cert_iss.ent_sig.sig_key); if (err) return (err); key = shkey_bin(enc_data, enc_len); free(enc_data); memcpy(&cert->cert_sub.ent_sig.sig_key, key, sizeof(shkey_t)); cert->cert_sub.ent_len = enc_len; shkey_free(&key); } cert->cert_flag |= SHCERT_CERT_CHAIN; cert->cert_flag |= parent->cert_flag; /* inherit parent's attributes */ cert->cert_sub.ent_sig.sig_key.alg = parent->cert_sub.ent_sig.sig_key.alg; strcpy(cert->cert_iss.ent_name, parent->cert_sub.ent_name); cert->cert_iss.ent_sig.sig_stamp = parent->cert_sub.ent_sig.sig_stamp; cert->cert_iss.ent_sig.sig_expire = parent->cert_sub.ent_sig.sig_expire; cert->cert_iss.ent_len = parent->cert_sub.ent_len; return (0); }
int sharedaemon_bcast_recv(void) { struct sockaddr_in addr; socklen_t addr_len; struct timeval to; fd_set read_set; shpeer_t *peer; char dgram[512]; ssize_t r_len; int err; err = bcast_recv_init(); if (err) { return (err); } FD_ZERO(&read_set); FD_SET(_bcast_recv_fd, &read_set); /* nonblocking read */ memset(&to, 0, sizeof(to)); err = select(_bcast_recv_fd+1, &read_set, NULL, NULL, &to); if (err < 0) { return (-errno); } if (err == 0) { //fprintf(stderr, "\rWaiting for select(_bcast_recv_fd).."); //fflush(stderr); return (0); /* nothing to read */ } addr_len = sizeof(addr); memset(&addr, 0, addr_len); r_len = recvfrom(_bcast_recv_fd, dgram, sizeof dgram, 0, &addr, &addr_len); if (r_len < 0) { fprintf(stderr, "DEBUG: %d = recvfrom()\n", r_len); return (-errno); } /* and who are you? */ if (r_len < sizeof(shpeer_t)) { fprintf(stderr, "DEBUG: <%d bytes> pending..\n", r_len); return (SHERR_INVAL); } #if 0 now = shtime(); tx = (tx_t *)dgram; if (shtime_after(tx->tx_stamp, now) || shtime_before(tx->tx_stamp, shtime_adj(now, -BROADCAST_TIMEOUT))) { /* broadcast message must indicate sane time-frame. */ return (SHERR_TIME); } switch (tx->tx_op) { case TX_PEER: peer_tx = (tx_peer_t *)dgram; if (0 != shkey_cmp(&tx->tx_peer, shpeer_kpriv(&peer_tx->peer))) return (SHERR_INVAL); /* only accept self-referencing broadcast */ } #endif /* share-daemon broadcasting it's peer address. */ peer = (shpeer_t *)dgram; if (!shkey_cmp(shpeer_kpub(sharedaemon_peer()), shpeer_kpub(peer))) { /* this is not a shared peer */ return (0); /* all done */ } if (!shkey_cmp(shpeer_kpub(sharedaemon_peer()), shpeer_kpub(peer))) { fprintf(stderr, "DEBUG: invalid key\n"); /* this is a peer referencing ourselves. */ //err = sharedaemon_netclient_alias(&addr); } switch (peer->type) { case SHNET_PEER_LOCAL: case SHNET_PEER_IPV4: /* memset(&addr, '\000', sizeof(struct sockaddr_in)); memcpy(&addr, &peer_tx->peer.addr, sizeof(peer_tx->peer.addr)); */ fprintf(stderr, "DEBUG: received UDP broadcast with peer \"%s\"\n", shpeer_print(peer)); fprintf(stderr, "DEBUG: received UDP broadcast for \"%s\" port %d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); if (!peer->addr.sin_port) break; /* otay */ addr.sin_family = AF_INET; err = sharedaemon_netclient_conn(peer, &addr); if (err) return (err); break; } fprintf(stderr, "DEBUG: processed bcast recv\n"); return (0); }