int tx_send(shpeer_t *cli_peer, tx_t *tx) { unsigned char *data = (unsigned char *)tx; size_t data_len; tx_ledger_t *l; int err; txop_t *op; if (!data) return (SHERR_INVAL); data_len = get_tx_size(tx); if (!data_len) return (0); op = get_tx_op(tx->tx_op); if (!op) return (SHERR_INVAL); if (op->op_send) { err = op->op_send(cli_peer, data); if (err) { if (err == SHERR_OPNOTSUPP) return (0); return (err); } } if (is_tx_stored(tx->tx_op)) { l = ledger_load(shpeer_kpriv(sharedaemon_peer()), shtime()); if (l) { ledger_tx_add(l, (tx_t *)data); ledger_close(l); } } #if 0 /* encapsulate for network transfer. */ tx_wrap(shpeer_kpriv(cli_peer), (tx_t *)tx); #endif if (cli_peer) { sched_tx_sink(shpeer_kpriv(cli_peer), data, data_len); } else { sched_tx(data, data_len); } return (0); }
void info_table_add_peer(info_table_t *table, char *col_name, shpeer_t *peer) { struct in_addr in_addr; int pid; if (!peer) return; info_table_add_str(table, "APP", peer->label); info_table_add_str(table, "GROUP", peer->group); info_table_add_key(table, "TOKEN", shpeer_kpub(peer)); info_table_add_key(table, "PRIV", shpeer_kpriv(peer)); if (peer->type == SHNET_PEER_IPV4 && peer->addr.sin_port) { info_table_add_int(table, "PORT", ntohs(peer->addr.sin_port)); } #if 0 if (run_flags & PFLAG_VERBOSE) { if (peer->arch & SHARCH_LINUX && peer->arch & SHARCH_32BIT) info_table_add_str(table, "ARCH", "LIN32"); else if (peer->arch & SHARCH_WIN && peer->arch & SHARCH_32BIT) info_table_add_str(table, "ARCH", "WIN32"); else if (peer->arch & SHARCH_LINUX) info_table_add_str(table, "ARCH", "LIN"); else if (peer->arch & SHARCH_WIN) info_table_add_str(table, "ARCH", "WIN"); } #endif pid = share_appinfo_pid(peer->label); info_table_add_int(table, "PID", pid); }
int txop_ward_confirm(shpeer_t *peer, tx_ward_t *ward) { tx_context_t *ctx; tx_t *tx; int err; #if 0 /* verify identity exists */ ctx = (tx_context_t *)tx_load(TX_CONTEXT, &ward->ward_ctx); if (!ctx) return (SHERR_NOKEY); /* .. */ pstore_free(ctx); err = confirm_signature(&ward->ward_sig, shpeer_kpriv(&ward->ward_peer), shkey_hex(&ward->ward_key)); pstore_free(tx); if (err) return (err); err = inittx_context(ctx, get_tx_key(ward), ashkey_uniq()); if (err) return (err); #endif return (0); }
int txop_ward_init(shpeer_t *cli_peer, tx_ward_t *ward) { unsigned char context[128]; shkey_t sig_key; tx_context_t ctx; tx_t *tx; int err; if (ward->ward_stamp == SHTIME_UNDEFINED) ward->ward_stamp = shtime(); if (ward->ward_expire == SHTIME_UNDEFINED) ward->ward_expire = shtime_adj(shtime(), MAX_SHARE_SESSION_TIME); memcpy(&ward->ward_tx.tx_peer, shpeer_kpriv(sharedaemon_peer()), sizeof(shpeer_t)); memset(&ctx, 0, sizeof(ctx)); err = inittx_context(&ctx, get_tx_key(ward), ashkey_uniq()); if (err) return (err); err = tx_save(&ctx); if (err) return (err); /* store key reference to generated context */ memcpy(&ward->ward_ctx, &ctx.ctx_tx.tx_key, sizeof(ward->ward_ctx)); return (0); }
int sharedaemon_bcast_send_peer(shpeer_t *peer) { struct sockaddr_in addr; socklen_t addr_len; struct timeval to; fd_set write_set; char dgram[512]; ssize_t w_len; int fd; int err; fd = bcast_send_init(); if (fd < 0) { fprintf(stderr, "DEBUG: sharedaemon_bcast_send: bcast_init error %d\n", err); return (err); } FD_ZERO(&write_set); FD_SET(fd, &write_set); /* nonblocking write */ memset(&to, 0, sizeof(to)); err = select(fd+1, NULL, &write_set, NULL, &to); if (err < 0) { close(fd); return (-errno); } if (err == 0) { close(fd); return (0); /* not able to send */ } memset(dgram, 0, sizeof(dgram)); memcpy(dgram, peer, sizeof(shpeer_t)); addr_len = sizeof(addr); memset(&addr, 0, addr_len); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); addr.sin_port = htons(SHARED_BROADCAST_PORT); w_len = sendto(fd, dgram, sizeof(shpeer_t), 0, &addr, sizeof(addr)); if (w_len < 0) { fprintf(stderr, "DEBUG: sharedaemon_bcast_send: sendto error: %s\n", strerror(errno)); close(fd); return (-errno); } fprintf(stderr, "DEBUG: sharedaemon_bcast_send: peer \"%s\" <%d bytes>\n", shpeer_print(peer), w_len); fprintf(stderr, "DEBUG: peer pubkey: %s\n", shkey_print(shpeer_kpub(peer))); fprintf(stderr, "DEBUG: peer priv key: %s\n", shkey_print(shpeer_kpriv(peer))); /* close socket; only used once. */ close(fd); return (0); }
int verify_asset_signature(tx_asset_t *asset, shpeer_t *peer) { uint64_t crc; int err; crc = shcrc((unsigned char *)asset->ass_data, asset->ass_size); err = shkey_verify(shpeer_kpriv(peer), crc, &asset->ass.ass_sig, asset->ass.ass_expire); if (err) return (err); return (0); }
void generate_asset_signature(tx_asset_t *asset, shpeer_t *peer) { shkey_t *sig_key; uint64_t crc; if (asset->ass.ass_expire == SHTIME_UNDEFINED) asset->ass.ass_expire = shtime_adj(shtime(), SHARE_DEFAULT_EXPIRE_TIME); crc = shcrc((unsigned char *)asset->ass_data, asset->ass_size); sig_key = shkey_cert(shpeer_kpriv(peer), crc, asset->ass.ass_expire); memcpy(&asset->ass.ass_sig, sig_key, sizeof(shkey_t)); shkey_free(&sig_key); }
shkey_t *get_bond_key(shkey_t *sender, shkey_t *receiver, shkey_t *ref) { static shkey_t ret_key; shkey_t keys[3]; shkey_t *key; if (!sender) sender = shpeer_kpriv(sharedaemon_peer()); else if (!receiver) receiver = shpeer_kpriv(sharedaemon_peer()); if (!ref) ref = ashkey_blank(); memcpy(&keys[0], sender, sizeof(shkey_t)); memcpy(&keys[1], receiver, sizeof(shkey_t)); memcpy(&keys[2], ref, sizeof(shkey_t)); key = shkey_bin(keys, sizeof(shkey_t) * 3); memcpy(&ret_key, key, sizeof(ret_key)); shkey_free(&key); return (&ret_key); }
static int validate_asset_signature(tx_asset_t *asset) { shpeer_t *peer; uint64_t crc; int err; peer = load_asset_peer(&asset->ass.ass_id); if (!peer) return (SHERR_INVAL); crc = shcrc((unsigned char *)asset->ass_data, asset->ass_size); err = shkey_verify(shpeer_kpriv(peer), crc, &asset->ass.ass_sig, asset->ass.ass_expire); if (err) return (err); return (0); }
/** * @param origin a peer reference to the sender of the bond */ tx_bond_t *load_bond_peer(shpeer_t *sender, shpeer_t *receiver, shpeer_t *ref) { return (load_bond(get_bond_key(shpeer_kpriv(sender), shpeer_kpriv(receiver), shpeer_kpub(ref)))); }
int remote_broadcast_bond(shpeer_t *origin, tx_bond_t *bond) { sched_tx_sink(shpeer_kpriv(origin), bond, sizeof(tx_bond_t)); return (0); }
/** * @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 remote_broadcast_asset(shpeer_t *origin, tx_asset_t *asset) { sched_tx_sink(shpeer_kpriv(origin), asset, sizeof(tx_asset_t)); return (0); }
int tx_recv(shpeer_t *cli_peer, tx_t *tx) { tx_ledger_t *l; tx_t *rec_tx; txop_t *op; int err; if (!tx) return (SHERR_INVAL); #if 0 if (ledger_tx_load(shpeer_kpriv(cli_peer), tx->hash, tx->tx_stamp)) { fprintf(stderr, "DEBUG: tx_recv: skipping duplicate tx '%s'\n", tx->hash); return (SHERR_NOTUNIQ); } #endif op = get_tx_op(tx->tx_op); if (!op) return (SHERR_INVAL); if (tx->tx_flag & TXF_WARD) { err = txward_confirm(tx); if (err) return (err); } /* check for dup in ledger (?) */ rec_tx = (tx_t *)tx_load(tx->tx_op, get_tx_key(tx)); if (!rec_tx) { rec_tx = (tx_t *)calloc(1, op->op_size); if (!rec_tx) return (SHERR_NOMEM); memcpy(rec_tx, tx, op->op_size); #if 0 err = tx_init(cli_peer, rec_tx); if (err) { pstore_free(rec_tx); return (err); } #endif err = tx_save(rec_tx); if (err) { pstore_free(rec_tx); return (err); } } if (op->op_recv) { err = op->op_recv(cli_peer, tx); if (err) { pstore_free(rec_tx); return (err); } } pstore_free(rec_tx); if (is_tx_stored(tx->tx_op)) { l = ledger_load(shpeer_kpriv(cli_peer), shtime()); if (l) { ledger_tx_add(l, tx); ledger_close(l); } } 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); }