/** * insert a new-AAAA entry in message * */ void DNSUpdate::addinMsg_newAAAA(){ DnsRR rr; rr.NAME = domainname(_hostname, *zoneroot); rr.TYPE = qtype_getcode("AAAA", false); rr.TTL = txt_to_int(ttl); string data = rr_fromstring(rr.TYPE, hostip, *zoneroot); rr.RDLENGTH = data.size(); rr.RDATA = (unsigned char*)memdup(data.c_str(), rr.RDLENGTH); message->authority.push_back(rr); Log(Debug) << "DDNS: AAAA record created:" << rr.NAME.tostring() << " -> " << hostip << LogEnd; }
/** * delete a single rr from rrset. If no such RRs exist, then this Update RR will be * silently ignored by the primary master. * */ void DNSUpdate::deleteAAAARecordFromRRSet(){ DnsRR rr; rr.NAME = domainname(_hostname, *zoneroot); rr.TYPE = qtype_getcode("AAAA", false); rr.CLASS = QCLASS_NONE; /* 254 */ rr.TTL = 0; string data = rr_fromstring(rr.TYPE, hostip, *zoneroot); rr.RDLENGTH = data.size(); rr.RDATA = (unsigned char*)memdup(data.c_str(), rr.RDLENGTH); message->authority.push_back(rr); Log(Debug) << "DDNS: AAAA record created:" << rr.NAME.tostring() << " -> " << hostip << LogEnd; }
stl_string calc_mac (DnsRR &tsig_rr, message_buff msg, stl_string sign_key, message_buff *extra) { struct hmac_md5_ctx md5; unsigned char md5res [MD5_DIGEST_SIZE]; memset (&md5, 0, sizeof (hmac_md5_ctx)); unsigned char *digestpos = rr_getdata (tsig_rr.RDATA, DNS_TYPE_TSIG, 3); uint16_t digestlen = uint16_value (digestpos); // print_buff (sign_key.size(), (unsigned char*)sign_key.c_str()); hmac_md5_set_key(&md5, sign_key.size(), (uint8_t *)sign_key.c_str()); // printf ("Begin MAC calculation\n"); /* original MAC */ if (extra && extra->len) hmac_md5_update(&md5, extra->len, extra->msg); /* message */ hmac_md5_update(&md5, 10, msg.msg); hmac_md5_update(&md5, 2, uint16_buff (uint16_value (msg.msg + 10) - 1)); hmac_md5_update(&md5, msg.len - 12, msg.msg + 12); /* tsig rr */ stl_string canname = tsig_rr.NAME.canonical(); hmac_md5_update(&md5, canname.size(), (const uint8_t *)canname.c_str()); hmac_md5_update(&md5, 2, uint16_buff (QCLASS_ANY)); hmac_md5_update(&md5, 4, uint32_buff (0)); /* start of TSIG rrdata */ domainname dom = domainname (true, tsig_rr.RDATA); canname = dom.canonical(); hmac_md5_update (&md5, canname.size(), (const uint8_t*)canname.c_str()); hmac_md5_update(&md5, 8, digestpos - 8); /* rest, excluding original ID */ hmac_md5_update(&md5, tsig_rr.RDLENGTH - (digestpos - tsig_rr.RDATA) - digestlen - 4, digestpos + digestlen + 4); hmac_md5_digest(&md5, MD5_DIGEST_SIZE, md5res); // printf ("End MAC calculation\n"); // print_buff (MD5_DIGEST_SIZE, md5res); stl_string ret; ret.append ((char*)md5res, MD5_DIGEST_SIZE); return ret; }
domainname guess_zone_name(const char *file) { const char *ptr = file + strlen(file) - 1; char tmp[256]; int t; while (ptr >= file) { if (*ptr == pathdelim) { ptr++; break; } ptr--; } t = strlen(ptr); if (tolower(ptr[0]) == 'd' && tolower(ptr[1]) == 'b' && ptr[2] == '.') { return ptr + 3; } else if (t >= 4 && (strncmpi(ptr + t - 4, ".prm", 4) == 0 || strncmpi(ptr + t - 4, ".dns", 4) == 0)) { if (strlen(ptr) - 4 >= 256) throw PException("File name too long!"); memcpy(tmp, ptr, t - 4); tmp[t - 4] = '\0'; return domainname((char*)tmp); } else return ptr; }
void DNSUpdate::addDHCID(const char* duid, int duidlen) { DnsRR rr; rr.NAME = domainname(_hostname, *zoneroot); rr.TYPE = qtype_getcode("DHCID", false); rr.TTL = txt_to_int(ttl); char input_buf[512]; char output_buf[35]; // identifier-type code (2) + digest type code (1) + digest (SHA-256 = 32 bytes) memcpy(input_buf, duid, duidlen); // memcpy(input_buf+duidlen, rr.NAME.c_str(), strlen((const char*)rr.NAME.c_str()) ); sha256_buffer(input_buf, duidlen + strlen((const char*)rr.NAME.c_str() ), output_buf+3); output_buf[0] = 0; output_buf[1] = 2; // identifier-type code: 0x0002 - DUID used as client identifier output_buf[2] = 1; // digest type = 1 (SHA-256) message->authority.push_back(rr); }
stl_string rrdata_convertdoms(rr_type *rr, domainname znroot, domainname origin, char *ptr) { stl_string ret, tmp; char *cptr = rr->properties; domainname tmpd; while (*cptr) { tmp = read_entry(ptr); if (*cptr == 'd' || *cptr == 'm') { /* domain name */ if (!(*cptr == 'm' && strchr(tmp.c_str(), '@')) && tmp[tmp.size() - 1] != '.') { /* domain name is relative to a non-root origin. convert it to a root origin */ tmpd = domainname(tmp.c_str(), origin); if (ret.size()) ret += " "; ret += tmpd.torelstring(znroot); cptr++; continue; } } if (ret.size()) ret += " "; ret += tmp; cptr++; } return ret; }
void read_master_file(const char *file, domainname &znroot, void *userdat, error_callback err, rr_callback rr_cb, rr_literal_callback rrl_cb, comment_callback comm_cb, int flags) { bool has_znroot = !(flags&POSLIB_MF_AUTOPROBE), has_soa = false; char buff[1024]; char *ptr, *p2; int c; bool ttl_given = false; stl_string ttl = "3600"; domainname origin, nam; int linenum = 1, linenum2; stl_string str, tmp, t2, t3, nm; DnsRR rr; rr_type *type = NULL; FILE *f = try_fopen_r(file); if (!f) throw PException(true, "Could not open %s", file); c = fgetc(f); if (c != EOF) ungetc(c, f); if (has_znroot) origin = znroot; try { begin: while (!feof(f)) { /* since the poslib functions will filter out comments, let's do them ourselves */ if (comm_cb) { c = fgetc(f); if (c == ';') { fgets(buff, 1024, f); ptr = buff + strlen(buff) - 1; while (ptr >= buff && (*ptr == '\n' || *ptr == '\r')) *ptr = '\0'; comm_cb(userdat, buff); continue; } ungetc(c, f); } try { read_line(buff, f, &linenum, &linenum2); } catch (PException p) { break; } if (buff[0] == 0) goto begin; ptr = buff; while (*ptr == ' ' || *ptr == '\t') ptr++; if (*ptr == '\0') continue; if (buff[0] == '$') { if (strncmpi(buff, "$ttl ", 4) == 0) { ttl = buff + 5; ttl_given = true; } else if (strncmpi(buff, "$origin ", 8) == 0) { /* origin */ origin = domainname(buff + 8, znroot); if (!has_znroot) { /* first entry. this is the zone root */ znroot = origin; has_znroot = true; } } else err(userdat, file, linenum2, PException(true, "Unknown directive %s", buff).message); continue; } if (!has_znroot) { znroot = guess_zone_name(file); origin = znroot; has_znroot = true; } if (buff[0] != ' ' && buff[0] != '\t') { nam = domainname(read_entry(ptr).c_str(), origin); } else if (!has_soa) { err(userdat, file, linenum2, "First record in zone should have a domain name! Using origin instead."); nam = origin; } /* can be class or ttl or rrtype */ while (1) { str = read_entry(ptr); if (str == "IN" || str == "HS" || str == "CH" || str == "HS" || str == "in" || str == "hs" || str == "ch" || str == "hs") { /* class */ continue; } else if ((type = rrtype_getinfo(str.c_str())) != NULL) { break; } else { try { txt_to_int(str.c_str()); ttl_given = true; } catch (PException p) { err(userdat, file, linenum2, PException(true, "Invalid TTL/RR type %s!", str.c_str()).message); goto begin; } ttl = str.c_str(); } } if (!has_soa) { if (type->type != DNS_TYPE_SOA) { if (!(flags & POSLIB_MF_NOSOA)) { err(userdat, file, linenum2, "First record was no SOA record; using default SOA record instead."); if (rr_cb) { rr.NAME = znroot; rr.TYPE = DNS_TYPE_SOA; rr.TTL = 3600; tmp = rr_fromstring(DNS_TYPE_SOA, "ns1 hostmaster 1 2h 1h 1d 2h", znroot); rr.RDLENGTH = tmp.size(); rr.RDATA = (unsigned char *)memdup(tmp.c_str(), tmp.size()); rr_cb(userdat, &rr); } if (rrl_cb) rrl_cb(userdat, "@", "1h", "SOA", "ns1 hostmaster 1 2h 1h 1d 2h", znroot); } else if (!ttl_given) { err(userdat, file, linenum2, "First record should have TTL value; using 1h for now."); ttl = "3600"; ttl_given = true; } } else { if (!ttl_given) { p2 = ptr; read_entry(p2); read_entry(p2); read_entry(p2); read_entry(p2); read_entry(p2); read_entry(p2); t3 = read_entry(p2); if (strlen(t3.c_str()) < 32) ttl = t3; } } has_soa = true; } else if (type->type == DNS_TYPE_SOA && !(flags & POSLIB_MF_NOSOA)) { err(userdat, file, linenum2, "Non-initial SOA record ignored"); continue; } if (!(nam >= znroot)) { err(userdat, file, linenum2, PException(true, "Ignoring domain name %s outside of zone %s!", nam.tocstr(), znroot.tocstr()).message); continue; } if (rr_cb) { try { rr.NAME = nam; rr.TYPE = type->type; rr.TTL = txt_to_int(ttl.c_str()); tmp = rr_fromstring(type->type, ptr, origin); rr.RDLENGTH = tmp.size(); rr.RDATA = (unsigned char *)memdup(tmp.c_str(), tmp.size()); rr_cb(userdat, &rr); } catch (PException p) { err(userdat, file, linenum2, p.message); } } if (rrl_cb) { try { t2 = ptr; nm = nam.torelstring(znroot); tmp = rr_fromstring(type->type, ptr, origin); if (origin != znroot) t2 = rrdata_convertdoms(type, znroot, origin, ptr); } catch (PException p) { err(userdat, file, linenum2, p.message); } rrl_cb(userdat, nm.c_str(), ttl.c_str(), type->name, t2.c_str(), znroot); } } } catch (PException p) { fclose(f); throw p; } fclose(f); }
void apop(Ticketreq *tr, int type) { int challen, i, tries; char *secret, *hkey, *p; Ticketreq treq; DigestState *s; char sbuf[SECRETLEN], hbuf[DESKEYLEN]; char tbuf[TICKREQLEN]; char buf[MD5dlen*2]; uchar digest[MD5dlen], resp[MD5dlen]; ulong rb[4]; char chal[256]; USED(tr); /* * Create a challenge and send it. */ randombytes((uchar*)rb, sizeof(rb)); p = chal; p += snprint(p, sizeof(chal), "<%lux%lux.%lux%lux@%s>", rb[0], rb[1], rb[2], rb[3], domainname()); challen = p - chal; print("%c%-5d%s", AuthOKvar, challen, chal); /* give user a few attempts */ for(tries = 0; ; tries++) { /* * get ticket request */ if(readn(0, tbuf, TICKREQLEN) < 0) exits(0); convM2TR(tbuf, &treq); tr = &treq; if(tr->type != type) exits(0); /* * read response */ if(readn(0, buf, MD5dlen*2) < 0) exits(0); for(i = 0; i < MD5dlen; i++) resp[i] = (h2b(buf[2*i])<<4)|h2b(buf[2*i+1]); /* * lookup */ secret = findsecret(KEYDB, tr->uid, sbuf); hkey = findkey(KEYDB, tr->hostid, hbuf); if(hkey == 0 || secret == 0){ replyerror("apop-fail bad response %s", raddr); logfail(tr->uid); if(tries > 5) return; continue; } /* * check for match */ if(type == AuthCram){ hmac_md5((uchar*)chal, challen, (uchar*)secret, strlen(secret), digest, nil); } else { s = md5((uchar*)chal, challen, 0, 0); md5((uchar*)secret, strlen(secret), digest, s); } if(memcmp(digest, resp, MD5dlen) != 0){ replyerror("apop-fail bad response %s", raddr); logfail(tr->uid); if(tries > 5) return; continue; } break; } succeed(tr->uid); /* * reply with ticket & authenticator */ if(tickauthreply(tr, hkey) < 0) exits(0); if(debug){ if(type == AuthCram) syslog(0, AUTHLOG, "cram-ok %s %s", tr->uid, raddr); else syslog(0, AUTHLOG, "apop-ok %s %s", tr->uid, raddr); } }