2 * itkacl control library, version 0.1
4 * (C) 2004-2009 Steinar H. Gunderson
16 struct itkacl_config {
20 #define CONFIG_FILENAME "/etc/itkacl.conf"
22 static int itkacl_read_config(const char * const filename,
23 struct itkacl_config *config,
24 char *errmsg, size_t errmsg_size)
29 strcpy(config->nszone, "");
31 fp = fopen(CONFIG_FILENAME, "r");
34 snprintf(errmsg, errmsg_size, "%s: %s",
35 CONFIG_FILENAME, strerror(errno));
40 char line[256], arg[256], *ptr;
42 if (fgets(line, sizeof(line), fp) == NULL) {
47 /* Remove trailing newlines and then comments. */
48 ptr = strchr(line, '\n');
52 ptr = strchr(line, '\r');
56 ptr = strchr(line, '#');
60 /* Remove trailing whitespace, if any. */
61 ptr = line + strlen(line) - 1;
62 while (ptr >= line && isspace(*ptr))
65 /* Skip lines that now ended up blank. */
69 if (sscanf(line, "zone %255s", arg) == 1) {
70 strcpy(config->nszone, arg);
75 snprintf(errmsg, errmsg_size, "%s: Could not parse line %d",
76 CONFIG_FILENAME, lineno);
81 if (strlen(config->nszone) == 0) {
83 snprintf(errmsg, errmsg_size, "%s: Missing 'zone' directive",
93 int itkacl_check(const char * const realm, const char * const user,
94 char *errmsg, size_t errmsg_size)
96 struct itkacl_config config;
97 struct hostent he, *he_ptr;
101 char temp[256], ns_temp[1024];
103 if (itkacl_read_config(CONFIG_FILENAME, &config, errmsg, errmsg_size) != 0) {
107 if (realm[0] != '/') {
109 snprintf(errmsg, errmsg_size, "Invalid realm '%s' (missing leading /)",
113 if (strlen(user) > 64) {
115 snprintf(errmsg, errmsg_size, "Invalid user '%s' (above 64 characters)",
119 if (strlen(realm) > 64) {
121 snprintf(errmsg, errmsg_size, "Invalid realm '%s' (above 64 characters)",
126 /* check that the user name is valid */
129 /* only allow [a-z0-9-] */
130 if (!((*ptr >= 'a' && *ptr <= 'z') ||
131 (*ptr >= '0' && *ptr <= '9') ||
134 snprintf(errmsg, errmsg_size, "Invalid realm '%s' (illegal characters)",
142 /* traverse the realm entry by entry from the root,
143 * creating a DNS zone name as we go */
144 strcpy(nszone, config.nszone);
147 /* copy all characters to next / or end of string */
153 while (*ptr && *ptr != '/') {
154 /* only allow [a-z0-9-] */
155 if (!((*ptr >= 'a' && *ptr <= 'z') ||
156 (*ptr >= '0' && *ptr <= '9') ||
159 snprintf(errmsg, errmsg_size, "Invalid realm '%s' (illegal characters)",
164 this_part[i++] = *ptr++;
168 strcpy(temp, nszone);
169 snprintf(nszone, 256, "%s.%s", this_part, temp);
172 /* finally, prepend the username */
173 strcpy(temp, nszone);
174 sprintf(nszone, "%s.%s", user, temp);
176 ret = gethostbyname_r(nszone, &he, ns_temp, 1024, &he_ptr, &host_errno);
179 * The man page for gethostbyname_r() specifies ret != 0 on failure, but
180 * that seemingly does not include HOST_NOT_FOUND failure.
182 if (he_ptr == NULL) {
183 // Not found => no access, but no error either.
184 if (host_errno == HOST_NOT_FOUND) {
188 switch (host_errno) {
190 snprintf(errmsg, errmsg_size, "Host name lookup failure");
193 snprintf(errmsg, errmsg_size, "Unknown server error");
196 snprintf(errmsg, errmsg_size, "No address associated with name");
199 snprintf(errmsg, errmsg_size, "Unknown DNS error %d", host_errno);
204 // The lookup succeeded, so we're good.