2 * ITKACL control library.
4 * (C) 2004-2013 Steinar H. Gunderson
16 struct itkacl_config {
19 char dnssec_public_key[256];
22 #define CONFIG_FILENAME "/etc/itkacl.conf"
24 static int itkacl_read_config(const char * const filename,
25 struct itkacl_config *config,
26 char *errmsg, size_t errmsg_size)
32 strcpy(config->nszone, "");
33 config->require_dnssec = 0;
34 strcpy(config->dnssec_public_key, "");
36 fp = fopen(CONFIG_FILENAME, "r");
39 snprintf(errmsg, errmsg_size, "%s: %s",
40 CONFIG_FILENAME, strerror(errno));
45 char line[256], arg[256], *ptr;
47 if (fgets(line, sizeof(line), fp) == NULL) {
52 /* Remove trailing newlines and then comments. */
53 ptr = strchr(line, '\n');
57 ptr = strchr(line, '\r');
61 ptr = strchr(line, '#');
65 /* Remove trailing whitespace, if any. */
66 ptr = line + strlen(line) - 1;
67 while (ptr >= line && isspace(*ptr))
70 /* Skip lines that now ended up blank. */
74 if (sscanf(line, "zone %255s", arg) == 1) {
75 strcpy(config->nszone, arg);
78 if (strcmp(line, "require-dnssec") == 0) {
79 config->require_dnssec = 1;
82 if (sscanf(line, "dnssec-public-key %255s", arg) == 1) {
83 strcpy(config->dnssec_public_key, arg);
88 snprintf(errmsg, errmsg_size, "%s: Could not parse line %d",
89 CONFIG_FILENAME, lineno);
94 if (strlen(config->nszone) == 0) {
96 snprintf(errmsg, errmsg_size, "%s: Missing 'zone' directive",
106 int itkacl_check(const char * const realm, const char * const user,
107 char *errmsg, size_t errmsg_size)
109 struct itkacl_config config;
115 struct ub_result* result;
117 if (itkacl_read_config(CONFIG_FILENAME, &config, errmsg, errmsg_size) != 0) {
121 if (realm[0] != '/') {
123 snprintf(errmsg, errmsg_size, "Invalid realm '%s' (missing leading /)",
127 if (strlen(user) > 64) {
129 snprintf(errmsg, errmsg_size, "Invalid user '%s' (above 64 characters)",
133 if (strlen(realm) > 64) {
135 snprintf(errmsg, errmsg_size, "Invalid realm '%s' (above 64 characters)",
140 /* check that the user name is valid */
143 /* only allow [a-z0-9-] */
144 if (!((*ptr >= 'a' && *ptr <= 'z') ||
145 (*ptr >= '0' && *ptr <= '9') ||
148 snprintf(errmsg, errmsg_size, "Invalid realm '%s' (illegal characters)",
156 /* traverse the realm entry by entry from the root,
157 * creating a DNS zone name as we go */
158 strcpy(nszone, config.nszone);
161 /* copy all characters to next / or end of string */
167 while (*ptr && *ptr != '/') {
168 /* only allow [a-z0-9-] */
169 if (!((*ptr >= 'a' && *ptr <= 'z') ||
170 (*ptr >= '0' && *ptr <= '9') ||
173 snprintf(errmsg, errmsg_size, "Invalid realm '%s' (illegal characters)",
178 this_part[i++] = *ptr++;
182 strcpy(temp, nszone);
183 snprintf(nszone, 256, "%s.%s", this_part, temp);
186 /* finally, prepend the username */
187 strcpy(temp, nszone);
188 sprintf(nszone, "%s.%s", user, temp);
190 /* Create the DNS resolver context. */
191 ctx = ub_ctx_create();
194 snprintf(errmsg, errmsg_size, "Host name lookup failure: Could not create DNS context");
198 ret = ub_ctx_resolvconf(ctx, "/etc/resolv.conf");
201 snprintf(errmsg, errmsg_size,
202 "Host name lookup failure: Could not read /etc/resolv.conf "
203 "(resolver error: %s) (system error: %s)",
204 ub_strerror(ret), strerror(errno));
209 ret = ub_ctx_hosts(ctx, "/etc/hosts");
212 snprintf(errmsg, errmsg_size,
213 "Host name lookup failure: Could not read /etc/hosts "
214 "(resolver error: %s) (system error: %s)",
215 ub_strerror(ret), strerror(errno));
220 if (strlen(config.dnssec_public_key) != 0) {
221 ret = ub_ctx_add_ta_file(ctx, config.dnssec_public_key);
224 snprintf(errmsg, errmsg_size,
225 "Host name lookup failure: Error adding keys from %s "
226 "(resolver error: %s) (system error: %s)",
227 config.dnssec_public_key,
228 ub_strerror(ret), strerror(errno));
234 /* Do the actual DNS lookup (TYPE A, CLASS IN). */
235 ret = ub_resolve(ctx, nszone, 1, 1, &result);
238 snprintf(errmsg, errmsg_size, "Host name lookup failure: %s",
247 snprintf(errmsg, errmsg_size,
248 "Host name lookup failure: Bogus DNSSEC result (security failure)");
249 ub_resolve_free(result);
253 if (config.require_dnssec && !result->secure) {
255 snprintf(errmsg, errmsg_size,
256 "Host name lookup failure: Result was not secured with DNSSEC");
257 ub_resolve_free(result);
262 nxdomain = result->nxdomain;
264 ub_resolve_free(result);