static int unhex_ucs2(const char *c, uint16_t *ret) { int aa, bb, cc, dd; uint16_t x; assert(c); assert(ret); aa = unhexchar(c[0]); if (aa < 0) return -EINVAL; bb = unhexchar(c[1]); if (bb < 0) return -EINVAL; cc = unhexchar(c[2]); if (cc < 0) return -EINVAL; dd = unhexchar(c[3]); if (dd < 0) return -EINVAL; x = ((uint16_t) aa << 12) | ((uint16_t) bb << 8) | ((uint16_t) cc << 4) | ((uint16_t) dd); if (x <= 0) return -EINVAL; *ret = x; return 0; }
int journal_file_parse_verification_key(JournalFile *f, const char *key) { uint8_t *seed; size_t seed_size, c; const char *k; int r; unsigned long long start, interval; seed_size = FSPRG_RECOMMENDED_SEEDLEN; seed = malloc(seed_size); if (!seed) return -ENOMEM; k = key; for (c = 0; c < seed_size; c++) { int x, y; while (*k == '-') k++; x = unhexchar(*k); if (x < 0) { free(seed); return -EINVAL; } k++; y = unhexchar(*k); if (y < 0) { free(seed); return -EINVAL; } k++; seed[c] = (uint8_t) (x * 16 + y); } if (*k != '/') { free(seed); return -EINVAL; } k++; r = sscanf(k, "%llx-%llx", &start, &interval); if (r != 2) { free(seed); return -EINVAL; } f->fsprg_seed = seed; f->fsprg_seed_size = seed_size; f->fss_start_usec = start * interval; f->fss_interval_usec = interval; return 0; }
_public_ int sd_id128_get_boot(sd_id128_t *ret) { static __thread sd_id128_t saved_boot_id; static __thread bool saved_boot_id_valid = false; _cleanup_close_ int fd = -1; char buf[36]; ssize_t k; unsigned j; sd_id128_t t; char *p; if (!ret) return -EINVAL; if (saved_boot_id_valid) { *ret = saved_boot_id; return 0; } fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return -errno; k = loop_read(fd, buf, 36, false); if (k < 0) return (int) k; if (k != 36) return -EIO; for (j = 0, p = buf; j < 16; j++) { int a, b; if (p >= buf + k) return -EIO; if (*p == '-') p++; a = unhexchar(p[0]); b = unhexchar(p[1]); if (a < 0 || b < 0) return -EIO; t.bytes[j] = a << 4 | b; p += 2; } saved_boot_id = t; saved_boot_id_valid = true; *ret = t; return 0; }
_public_ int sd_id128_get_boot(sd_id128_t *ret) { static thread_local sd_id128_t saved_boot_id; static thread_local bool saved_boot_id_valid = false; _cleanup_close_ int fd = -1; char buf[36]; unsigned j; sd_id128_t t; char *p; int r; assert_return(ret, -EINVAL); if (saved_boot_id_valid) { *ret = saved_boot_id; return 0; } fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return -errno; r = loop_read_exact(fd, buf, 36, false); if (r < 0) return r; for (j = 0, p = buf; j < 16; j++) { int a, b; if (p >= buf + 35) return -EIO; if (*p == '-') { p++; if (p >= buf + 35) return -EIO; } a = unhexchar(p[0]); b = unhexchar(p[1]); if (a < 0 || b < 0) return -EIO; t.bytes[j] = a << 4 | b; p += 2; } saved_boot_id = t; saved_boot_id_valid = true; *ret = t; return 0; }
_public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) { unsigned n, i; sd_id128_t t; bool is_guid = false; if (!s) return -EINVAL; if (!ret) return -EINVAL; for (n = 0, i = 0; n < 16;) { int a, b; if (s[i] == '-') { /* Is this a GUID? Then be nice, and skip over * the dashes */ if (i == 8) is_guid = true; else if (i == 13 || i == 18 || i == 23) { if (!is_guid) return -EINVAL; } else return -EINVAL; i++; continue; } a = unhexchar(s[i++]); if (a < 0) return -EINVAL; b = unhexchar(s[i++]); if (b < 0) return -EINVAL; t.bytes[n++] = (a << 4) | b; } if (i != (is_guid ? 36 : 32)) return -EINVAL; if (s[i] != 0) return -EINVAL; *ret = t; return 0; }
_public_ int sd_id128_get_machine(sd_id128_t *ret) { static __thread sd_id128_t saved_machine_id; static __thread bool saved_machine_id_valid = false; _cleanup_close_ int fd = -1; char buf[33]; ssize_t k; unsigned j; sd_id128_t t; if (!ret) return -EINVAL; if (saved_machine_id_valid) { *ret = saved_machine_id; return 0; } fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return -errno; k = loop_read(fd, buf, 33, false); if (k < 0) return (int) k; if (k != 33) return -EIO; if (buf[32] !='\n') return -EIO; for (j = 0; j < 16; j++) { int a, b; a = unhexchar(buf[j*2]); b = unhexchar(buf[j*2+1]); if (a < 0 || b < 0) return -EIO; t.bytes[j] = a << 4 | b; } saved_machine_id = t; saved_machine_id_valid = true; *ret = t; return 0; }
_public_ int sd_id128_get_machine(sd_id128_t *ret) { static thread_local sd_id128_t saved_machine_id; static thread_local bool saved_machine_id_valid = false; _cleanup_close_ int fd = -1; char buf[33]; unsigned j; sd_id128_t t; int r; assert_return(ret, -EINVAL); if (saved_machine_id_valid) { *ret = saved_machine_id; return 0; } fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return -errno; r = loop_read_exact(fd, buf, 33, false); if (r < 0) return r; if (buf[32] !='\n') return -EIO; for (j = 0; j < 16; j++) { int a, b; a = unhexchar(buf[j*2]); b = unhexchar(buf[j*2+1]); if (a < 0 || b < 0) return -EIO; t.bytes[j] = a << 4 | b; } saved_machine_id = t; saved_machine_id_valid = true; *ret = t; return 0; }
int make_command( const char *line, char **buffer, int *blen ) { int len = strlen(line), pos; *buffer = malloc( len ); *blen = 0; if(!*buffer) { perror("malloc"); return 0; } for(pos = 0; pos < len; pos++) { if(!isxdigit(line[pos])) continue; if(! (pos+1 < len) ) continue; (*buffer)[*blen] = unhexchar(line[pos]) * 16 + unhexchar(line[pos+1]); pos += 1; *blen += 1; } return 1; }
static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) { size_t sz; unsigned i; assert(c); assert(p); p += strspn(p, WHITESPACE); sz = strlen(p); if (sz % 2 != 0) return -EINVAL; sz /= 2; if (!c->capability) { c->capability = new0(uint8_t, sz * 4); if (!c->capability) return -ENOMEM; c->capability_size = sz * 4; } for (i = 0; i < sz; i ++) { int x, y; x = unhexchar(p[i*2]); y = unhexchar(p[i*2+1]); if (x < 0 || y < 0) return -EINVAL; c->capability[offset * sz + (sz - i - 1)] = (uint8_t) x << 4 | (uint8_t) y; } return 0; }
static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) { size_t sz, max; unsigned i, j; assert(c); assert(p); max = DIV_ROUND_UP(cap_last_cap(), 32U); p += strspn(p, WHITESPACE); sz = strlen(p); if (sz % 8 != 0) return -EINVAL; sz /= 8; if (sz > max) return -EINVAL; if (!c->capability) { c->capability = new0(uint32_t, max * 4); if (!c->capability) return -ENOMEM; } for (i = 0; i < sz; i ++) { uint32_t v = 0; for (j = 0; j < 8; ++j) { int t; t = unhexchar(*p++); if (t < 0) return -EINVAL; v = (v << 4) | t; } c->capability[offset * max + (sz - i - 1)] = v; } return 0; }
static int shorten_uuid(char destination[36], const char *source) { unsigned i, j; for (i = 0, j = 0; i < 36 && j < 32; i++) { int t; t = unhexchar(source[i]); if (t < 0) continue; destination[j++] = hexchar(t); } if (i == 36 && j == 32) { destination[32] = '\n'; destination[33] = 0; return 0; } return -EINVAL; }
int config_parse_duid_rawdata( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { DUID *ret = data; uint8_t raw_data[MAX_DUID_LEN]; unsigned count = 0; assert(filename); assert(lvalue); assert(rvalue); assert(ret); /* RawData contains DUID in format "NN:NN:NN..." */ for (;;) { int n1, n2, len, r; uint32_t byte; _cleanup_free_ char *cbyte = NULL; r = extract_first_word(&rvalue, &cbyte, ":", 0); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to read DUID, ignoring assignment: %s.", rvalue); return 0; } if (r == 0) break; if (count >= MAX_DUID_LEN) { log_syntax(unit, LOG_ERR, filename, line, 0, "Max DUID length exceeded, ignoring assignment: %s.", rvalue); return 0; } len = strlen(cbyte); if (!IN_SET(len, 1, 2)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid length - DUID byte: %s, ignoring assignment: %s.", cbyte, rvalue); return 0; } n1 = unhexchar(cbyte[0]); if (len == 2) n2 = unhexchar(cbyte[1]); else n2 = 0; if (n1 < 0 || n2 < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid DUID byte: %s. Ignoring assignment: %s.", cbyte, rvalue); return 0; } byte = ((uint8_t) n1 << (4 * (len-1))) | (uint8_t) n2; raw_data[count++] = byte; } assert_cc(sizeof(raw_data) == sizeof(ret->raw_data)); memcpy(ret->raw_data, raw_data, count); ret->raw_data_len = count; return 0; }
static void test_unhexchar(void) { assert_se(unhexchar('a') == 0xA); assert_se(unhexchar('A') == 0xA); assert_se(unhexchar('0') == 0x0); }
int config_parse_duid_rawdata( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { int r, n1, n2, byte; char *cbyte; const char *pduid = rvalue; Manager *m = userdata; Network *n = userdata; DUIDType duidtype; uint16_t dhcp_duid_type = 0; uint8_t dhcp_duid[MAX_DUID_LEN]; size_t len, count = 0, duid_start_offset = 0, dhcp_duid_len = 0; assert(filename); assert(lvalue); assert(rvalue); assert(userdata); duidtype = (ltype == DUID_CONFIG_SOURCE_GLOBAL) ? m->duid_type : n->duid_type; if (duidtype == _DUID_TYPE_INVALID) duidtype = DUID_TYPE_RAW; switch (duidtype) { case DUID_TYPE_LLT: /* RawData contains DUID-LLT link-layer address (offset 6) */ duid_start_offset = 6; break; case DUID_TYPE_EN: /* RawData contains DUID-EN identifier (offset 4) */ duid_start_offset = 4; break; case DUID_TYPE_LL: /* RawData contains DUID-LL link-layer address (offset 2) */ duid_start_offset = 2; break; case DUID_TYPE_UUID: /* RawData specifies UUID (offset 0) - fall thru */ case DUID_TYPE_RAW: /* First two bytes of RawData is DUID Type - fall thru */ default: break; } if (duidtype != DUID_TYPE_RAW) dhcp_duid_type = (uint16_t)duidtype; /* RawData contains DUID in format " NN:NN:NN... " */ for (;;) { r = extract_first_word(&pduid, &cbyte, ":", 0); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to read DUID, ignoring assignment: %s.", rvalue); goto exit; } if (r == 0) break; if ((duid_start_offset + dhcp_duid_len) >= MAX_DUID_LEN) { log_syntax(unit, LOG_ERR, filename, line, 0, "Max DUID length exceeded, ignoring assignment: %s.", rvalue); goto exit; } len = strlen(cbyte); if ((len == 0) || (len > 2)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid length - DUID byte: %s, ignoring assignment: %s.", cbyte, rvalue); goto exit; } n2 = 0; n1 = unhexchar(cbyte[0]); if (len == 2) n2 = unhexchar(cbyte[1]); if ((n1 < 0) || (n2 < 0)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid DUID byte: %s. Ignoring assignment: %s.", cbyte, rvalue); goto exit; } byte = (n1 << (4 * (len-1))) | n2; /* If DUID_TYPE_RAW, first two bytes hold DHCP DUID type code */ if ((duidtype == DUID_TYPE_RAW) && (count < 2)) { dhcp_duid_type |= (byte << (8 * (1 - count))); count++; continue; } dhcp_duid[duid_start_offset + dhcp_duid_len] = byte; dhcp_duid_len++; } if (ltype == DUID_CONFIG_SOURCE_GLOBAL) { m->duid_type = duidtype; m->dhcp_duid_type = dhcp_duid_type; m->dhcp_duid_len = dhcp_duid_len; memcpy(&m->dhcp_duid[duid_start_offset], dhcp_duid, dhcp_duid_len); } else { /* DUID_CONFIG_SOURCE_NETWORK */ n->duid_type = duidtype; n->dhcp_duid_type = dhcp_duid_type; n->dhcp_duid_len = dhcp_duid_len; memcpy(&n->dhcp_duid[duid_start_offset], dhcp_duid, dhcp_duid_len); } exit: return 0; }