/* * ntp_crypto_random_buf: * * Returns 0 on success, -1 on error. */ int ntp_crypto_random_buf( void *buf, size_t nbytes ) { #ifdef USE_OPENSSL_CRYPTO_RAND int rc; rc = RAND_bytes(buf, size2int_chk(nbytes)); if (1 != rc) { unsigned long err; char *err_str; err = ERR_get_error(); err_str = ERR_error_string(err, NULL); /* XXX: Log the error */ (void)&err_str; return -1; } return 0; #else arc4random_buf(buf, nbytes); return 0; #endif }
/* * sendrequest - format and send a request packet * * Historically, ntpdc has used a fixed-size request packet regardless * of the actual payload size. When authenticating, the timestamp, key * ID, and digest have been placed just before the end of the packet. * With the introduction in late 2009 of support for authenticated * ntpdc requests using larger 20-octet digests (vs. 16 for MD5), we * come up four bytes short. * * To maintain interop while allowing for larger digests, the behavior * is unchanged when using 16-octet digests. For larger digests, the * timestamp, key ID, and digest are placed immediately following the * request payload, with the overall packet size variable. ntpd can * distinguish 16-octet digests by the overall request size being * REQ_LEN_NOMAC + 4 + 16 with the auth bit enabled. When using a * longer digest, that request size should be avoided. * * With the form used with 20-octet and larger digests, the timestamp, * key ID, and digest are located by ntpd relative to the start of the * packet, and the size of the digest is then implied by the packet * size. */ static int sendrequest( int implcode, int reqcode, int auth, size_t qitems, size_t qsize, const char *qdata ) { struct req_pkt qpkt; size_t datasize; size_t reqsize; u_long key_id; l_fp ts; l_fp * ptstamp; size_t maclen; char * pass; ZERO(qpkt); qpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0); qpkt.implementation = (u_char)implcode; qpkt.request = (u_char)reqcode; datasize = qitems * qsize; if (datasize && qdata != NULL) { memcpy(qpkt.u.data, qdata, datasize); qpkt.err_nitems = ERR_NITEMS(0, qitems); qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize); } else { qpkt.err_nitems = ERR_NITEMS(0, 0); qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize); /* allow for optional first item */ } if (!auth || (keyid_entered && info_auth_keyid == 0)) { qpkt.auth_seq = AUTH_SEQ(0, 0); return sendpkt(&qpkt, req_pkt_size); } if (info_auth_keyid == 0) { key_id = getkeyid("Keyid: "); if (!key_id) { fprintf(stderr, "Invalid key identifier\n"); return 1; } info_auth_keyid = key_id; } if (!authistrusted(info_auth_keyid)) { pass = getpass_keytype(info_auth_keytype); if ('\0' == pass[0]) { fprintf(stderr, "Invalid password\n"); return 1; } authusekey(info_auth_keyid, info_auth_keytype, (u_char *)pass); authtrust(info_auth_keyid, 1); } qpkt.auth_seq = AUTH_SEQ(1, 0); if (info_auth_hashlen > 16) { /* * Only ntpd which expects REQ_LEN_NOMAC plus maclen * octets in an authenticated request using a 16 octet * digest (that is, a newer ntpd) will handle digests * larger than 16 octets, so for longer digests, do * not attempt to shorten the requests for downlevel * ntpd compatibility. */ if (REQ_LEN_NOMAC != req_pkt_size) return 1; reqsize = REQ_LEN_HDR + datasize + sizeof(*ptstamp); /* align to 32 bits */ reqsize = (reqsize + 3) & ~3; } else reqsize = req_pkt_size; ptstamp = (void *)((char *)&qpkt + reqsize); ptstamp--; get_systime(&ts); L_ADD(&ts, &delay_time); HTONL_FP(&ts, ptstamp); maclen = authencrypt( info_auth_keyid, (void *)&qpkt, size2int_chk(reqsize)); if (!maclen) { fprintf(stderr, "Key not found\n"); return 1; } else if (maclen != (size_t)(info_auth_hashlen + sizeof(keyid_t))) { fprintf(stderr, "%zu octet MAC, %zu expected with %zu octet digest\n", maclen, (info_auth_hashlen + sizeof(keyid_t)), info_auth_hashlen); return 1; } return sendpkt(&qpkt, reqsize + maclen); }