static ssize_t encrypt_challenge(struct master_config* config, struct udpaddress* remote, struct udpaddress* local, struct cipher_context* oldkey, const char* newkey, char* obuf) { char token[1500]; size_t tlength; tlength = create_challenge(config, remote, local, oldkey, newkey, token); return xencrypt(config, config->keyX, token, tlength, obuf); }
static void encrypt_and_write(struct master_config* config, int fd, const struct udpaddress* address, struct cipher_context* key, const char* ibuf, ssize_t ilength) { char sbuf[1500], buf[128]; ssize_t slength; slength = xencrypt(config, key, ibuf, ilength, sbuf); fprintf(stderr, "!!writing %d bytes to %s\n", (int) slength, udpaddress_string(address, buf)); if (datagram_write(fd, sbuf, slength, address) < 0) { fprintf(stderr, "write_offer datagram_write failed. Address: %s\n", udpaddress_string(address, buf)); } }
/* send encrypted packet */ int vpn_send(int fd, vpn_crypt_t *cry, vpn_proto_t type, const void *buf, size_t buflen) { vpn_hdr_t hdr; gcry_cipher_hd_t hd = NULL; char bigpack[VPN_BIGPACKET], encpack[VPN_BIGPACKET], xiv[256], *s; int pad = ~((buflen % cry->blklen) - cry->blklen)+1; int re, rs, rc, rx; switch(type) { case VPN_CLIENT: hd = cry->hsrc; break; case VPN_SERVER: hd = cry->hdst; } /* fill header */ hdr.pad = pad == cry->blklen ? 0 : pad; hdr.checksum = buflen + hdr.pad; /* check buffer size */ if(sizeof(bigpack) < hdr.checksum) return xmsg(-1, VPN_DEBUG|VPN_INFO, "packet too big to send: %d data bytes + %d header bytes\n", buflen, sizeof(hdr)); /* copy data to `bigpack' */ memset(bigpack, 0, sizeof(bigpack)); memcpy(&bigpack, buf, buflen); if(!cry->rndsend) cry->rndsend = initial_iv_random; memset(xiv, 0, sizeof(xiv)); gen_iv(xiv, cry->blklen, cry->rndsend); /* xmsg(0, VPN_DEBUG, "send using iv: %s\n", xiv); */ re = xencrypt(hd, cry->blklen, xiv, encpack, sizeof(encpack), bigpack, hdr.checksum); if(re == -1 || re != hdr.checksum) return xmsg(-1, VPN_DEBUG|VPN_INFO, "vpn_send: cannot encrypt packet (%d != %d)\n", re, hdr.checksum); /* send header */ rs = send(fd, &hdr, sizeof(hdr), 0); if(rs == -1) return rs; else if(!rs) return xmsg(0, VPN_DEBUG|VPN_INFO, "vpn_send: lost connection, peer disconnected\n"); else if(rs != sizeof(hdr)) return xmsg(-1, VPN_DEBUG|VPN_INFO, "vpn_send: partial send of header not allowed\n"); xmsg(0, VPN_DEBUG, "sent %d bytes header, checksum=%d and pad=%d\n", rs, hdr.checksum, hdr.pad); /* send data */ s = encpack; rc = re; rx = 0; do { rs = safe_send(fd, s, rc); if(rs == -1) return rs; else if(!rs) return xmsg(0, VPN_DEBUG|VPN_INFO, "vpn_send: lost connection, peer disconnected\n"); xmsg(0, VPN_DEBUG, "sent %d bytes of packet...\n", rs); s += rs; rx += rs; rc -= rs; } while(rx < re); cry->rndsend = buflen; return buflen; }
int main(int argc, char **argv) { char name[MAXNETNAMELEN+1]; char public[HEXKEYBYTES + 1]; char secret[HEXKEYBYTES + 1]; char crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE + 1]; char crypt2[HEXKEYBYTES + KEYCHECKSUMSIZE + 1]; int status; char *pass; struct passwd *pw; uid_t uid; int force = 0; int ch; #ifdef YP char *master; #endif while ((ch = getopt(argc, argv, "f")) != -1) switch(ch) { case 'f': force = 1; break; default: usage(); } argc -= optind; argv += optind; if (argc != 0) usage(); #ifdef YP yp_get_default_domain(&domain); if (yp_master(domain, PKMAP, &master) != 0) errx(1, "can't find master of publickey database"); #endif uid = getuid() /*geteuid()*/; if (uid == 0) { if (host2netname(name, NULL, NULL) == 0) errx(1, "cannot convert hostname to netname"); } else { if (user2netname(name, uid, NULL) == 0) errx(1, "cannot convert username to netname"); } printf("Generating new key for %s.\n", name); if (!force) { if (uid != 0) { #ifdef YPPASSWD pw = ypgetpwuid(uid); #else pw = getpwuid(uid); #endif if (pw == NULL) { #ifdef YPPASSWD errx(1, "no NIS password entry found: can't change key"); #else errx(1, "no password entry found: can't change key"); #endif } } else { pw = getpwuid(0); if (pw == NULL) errx(1, "no password entry found: can't change key"); } } pass = getpass("Password:"******"invalid password"); } #else force = 1; /* Make this mandatory */ #endif genkeys(public, secret, pass); memcpy(crypt1, secret, HEXKEYBYTES); memcpy(crypt1 + HEXKEYBYTES, secret, KEYCHECKSUMSIZE); crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0; xencrypt(crypt1, pass); if (force) { memcpy(crypt2, crypt1, HEXKEYBYTES + KEYCHECKSUMSIZE + 1); xdecrypt(crypt2, getpass("Retype password:"******"password incorrect"); } #ifdef YP printf("Sending key change request to %s...\n", master); #endif status = setpublicmap(name, public, crypt1); if (status != 0) { #ifdef YP errx(1, "unable to update NIS database (%u): %s", status, yperr_string(status)); #else errx(1, "unable to update publickey database"); #endif } if (uid == 0) { /* * Root users store their key in /etc/$ROOTKEY so * that they can auto reboot without having to be * around to type a password. Storing this in a file * is rather dubious: it should really be in the EEPROM * so it does not go over the net. */ int fd; fd = open(ROOTKEY, O_WRONLY|O_TRUNC|O_CREAT, 0); if (fd < 0) { warn("%s", ROOTKEY); } else { char newline = '\n'; if (write(fd, secret, strlen(secret)) < 0 || write(fd, &newline, sizeof(newline)) < 0) warn("%s: write", ROOTKEY); } } if (key_setsecret(secret) < 0) errx(1, "unable to login with new secret key"); printf("Done.\n"); exit(0); /* NOTREACHED */ }