2 * "$Id: cert.c 11173 2013-07-23 12:31:34Z msweet $"
4 * Authentication certificate routines for the CUPS scheduler.
6 * Copyright 2007-2012 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
17 * cupsdAddCert() - Add a certificate.
18 * cupsdDeleteCert() - Delete a single certificate.
19 * cupsdDeleteAllCerts() - Delete all certificates...
20 * cupsdFindCert() - Find a certificate.
21 * cupsdInitCerts() - Initialize the certificate "system" and root
26 * Include necessary headers...
32 # ifdef HAVE_MEMBERSHIP_H
33 # include <membership.h>
34 # endif /* HAVE_MEMBERSHIP_H */
35 #endif /* HAVE_ACL_INIT */
39 * 'cupsdAddCert()' - Add a certificate.
43 cupsdAddCert(int pid, /* I - Process ID */
44 const char *username, /* I - Username */
45 int type) /* I - AuthType for username */
47 int i; /* Looping var */
48 cupsd_cert_t *cert; /* Current certificate */
49 int fd; /* Certificate file */
50 char filename[1024]; /* Certificate filename */
51 static const char hex[] = "0123456789ABCDEF";
52 /* Hex constants... */
55 cupsdLogMessage(CUPSD_LOG_DEBUG2,
56 "cupsdAddCert: Adding certificate for PID %d", pid);
59 * Allocate memory for the certificate...
62 if ((cert = calloc(sizeof(cupsd_cert_t), 1)) == NULL)
66 * Fill in the certificate information...
71 strlcpy(cert->username, username, sizeof(cert->username));
73 for (i = 0; i < 32; i ++)
74 cert->certificate[i] = hex[CUPS_RAND() & 15];
77 * Save the certificate to a file readable only by the User and Group
78 * (or root and SystemGroup for PID == 0)...
81 snprintf(filename, sizeof(filename), "%s/certs/%d", StateDir, pid);
84 if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400)) < 0)
86 cupsdLogMessage(CUPSD_LOG_ERROR,
87 "Unable to create certificate file %s - %s",
88 filename, strerror(errno));
96 acl_t acl; /* ACL information */
97 acl_entry_t entry; /* ACL entry */
98 acl_permset_t permset; /* Permissions */
99 # ifdef HAVE_MBR_UID_TO_UUID
100 uuid_t group; /* Group ID */
101 # endif /* HAVE_MBR_UID_TO_UUID */
102 static int acls_not_supported = 0;
104 #endif /* HAVE_ACL_INIT */
108 * Root certificate...
112 fchown(fd, RunUser, SystemGroupIDs[0]);
114 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddCert: NumSystemGroups=%d",
118 if (NumSystemGroups > 1)
121 * Set POSIX ACLs for the root certificate so that all system
122 * groups can access it...
125 int j; /* Looping var */
127 # ifdef HAVE_MBR_UID_TO_UUID
129 * On MacOS X, ACLs use UUIDs instead of GIDs...
132 acl = acl_init(NumSystemGroups - 1);
134 for (i = 1; i < NumSystemGroups; i ++)
137 * Add each group ID to the ACL...
140 for (j = 0; j < i; j ++)
141 if (SystemGroupIDs[j] == SystemGroupIDs[i])
145 continue; /* Skip duplicate groups */
147 acl_create_entry(&acl, &entry);
148 acl_get_permset(entry, &permset);
149 acl_add_perm(permset, ACL_READ_DATA);
150 acl_set_tag_type(entry, ACL_EXTENDED_ALLOW);
151 mbr_gid_to_uuid((gid_t)SystemGroupIDs[i], group);
152 acl_set_qualifier(entry, &group);
153 acl_set_permset(entry, permset);
158 * POSIX ACLs need permissions for owner, group, other, and mask
159 * in addition to the rest of the system groups...
162 acl = acl_init(NumSystemGroups + 3);
165 acl_create_entry(&acl, &entry);
166 acl_get_permset(entry, &permset);
167 acl_add_perm(permset, ACL_READ);
168 acl_set_tag_type(entry, ACL_USER_OBJ);
169 acl_set_permset(entry, permset);
172 acl_create_entry(&acl, &entry);
173 acl_get_permset(entry, &permset);
174 acl_add_perm(permset, ACL_READ);
175 acl_set_tag_type(entry, ACL_GROUP_OBJ);
176 acl_set_permset(entry, permset);
179 acl_create_entry(&acl, &entry);
180 acl_get_permset(entry, &permset);
181 acl_add_perm(permset, 0);
182 acl_set_tag_type(entry, ACL_OTHER);
183 acl_set_permset(entry, permset);
186 acl_create_entry(&acl, &entry);
187 acl_get_permset(entry, &permset);
188 acl_add_perm(permset, ACL_READ);
189 acl_set_tag_type(entry, ACL_MASK);
190 acl_set_permset(entry, permset);
192 for (i = 1; i < NumSystemGroups; i ++)
195 * Add each group ID to the ACL...
198 for (j = 0; j < i; j ++)
199 if (SystemGroupIDs[j] == SystemGroupIDs[i])
203 continue; /* Skip duplicate groups */
205 acl_create_entry(&acl, &entry);
206 acl_get_permset(entry, &permset);
207 acl_add_perm(permset, ACL_READ);
208 acl_set_tag_type(entry, ACL_GROUP);
209 acl_set_qualifier(entry, SystemGroupIDs + i);
210 acl_set_permset(entry, permset);
215 char *text, *textptr; /* Temporary string */
217 cupsdLogMessage(CUPSD_LOG_ERROR, "ACL did not validate: %s",
219 text = acl_to_text(acl, NULL);
220 for (textptr = strchr(text, '\n');
222 textptr = strchr(textptr + 1, '\n'))
225 cupsdLogMessage(CUPSD_LOG_ERROR, "ACL: %s", text);
228 # endif /* HAVE_MBR_UID_TO_UUID */
230 if (acl_set_fd(fd, acl))
232 if (errno != EOPNOTSUPP || !acls_not_supported)
233 cupsdLogMessage(CUPSD_LOG_ERROR,
234 "Unable to set ACLs on root certificate \"%s\" - %s",
235 filename, strerror(errno));
237 if (errno == EOPNOTSUPP)
238 acls_not_supported = 1;
243 #endif /* HAVE_ACL_INIT */
245 RootCertTime = time(NULL);
254 fchown(fd, User, Group);
257 DEBUG_printf(("ADD pid=%d, username=%s, cert=%s\n", pid, username,
260 write(fd, cert->certificate, strlen(cert->certificate));
264 * Insert the certificate at the front of the list...
273 * 'cupsdDeleteCert()' - Delete a single certificate.
277 cupsdDeleteCert(int pid) /* I - Process ID */
279 cupsd_cert_t *cert, /* Current certificate */
280 *prev; /* Previous certificate */
281 char filename[1024]; /* Certificate file */
284 for (prev = NULL, cert = Certs; cert != NULL; prev = cert, cert = cert->next)
285 if (cert->pid == pid)
288 * Remove this certificate from the list...
291 cupsdLogMessage(CUPSD_LOG_DEBUG2,
292 "cupsdDeleteCert: Removing certificate for PID %d", pid);
294 DEBUG_printf(("DELETE pid=%d, username=%s, cert=%s\n", cert->pid,
295 cert->username, cert->certificate));
300 prev->next = cert->next;
305 * Delete the file and return...
308 snprintf(filename, sizeof(filename), "%s/certs/%d", StateDir, pid);
309 if (unlink(filename))
310 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to remove %s!", filename);
318 * 'cupsdDeleteAllCerts()' - Delete all certificates...
322 cupsdDeleteAllCerts(void)
324 cupsd_cert_t *cert, /* Current certificate */
325 *next; /* Next certificate */
326 char filename[1024]; /* Certificate file */
330 * Loop through each certificate, deleting them...
333 for (cert = Certs; cert != NULL; cert = next)
339 snprintf(filename, sizeof(filename), "%s/certs/%d", StateDir, cert->pid);
340 if (unlink(filename))
341 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to remove %s!", filename);
357 * 'cupsdFindCert()' - Find a certificate.
360 cupsd_cert_t * /* O - Matching certificate or NULL */
361 cupsdFindCert(const char *certificate) /* I - Certificate */
363 cupsd_cert_t *cert; /* Current certificate */
366 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindCert(certificate=%s)",
368 for (cert = Certs; cert != NULL; cert = cert->next)
369 if (!_cups_strcasecmp(certificate, cert->certificate))
371 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindCert: Returning %s...",
376 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindCert: Certificate not found!");
383 * 'cupsdInitCerts()' - Initialize the certificate "system" and root
390 #ifndef HAVE_ARC4RANDOM
391 cups_file_t *fp; /* /dev/random file */
395 * Initialize the random number generator using the random device or
396 * the current time, as available...
399 if ((fp = cupsFileOpen("/dev/urandom", "rb")) == NULL)
401 struct timeval tod; /* Time of day */
404 * Get the time in usecs and use it as the initial seed...
407 gettimeofday(&tod, NULL);
409 CUPS_SRAND((unsigned)(tod.tv_sec + tod.tv_usec));
413 unsigned seed; /* Seed for random number generator */
416 * Read 4 random characters from the random device and use
417 * them as the seed...
420 seed = cupsFileGetChar(fp);
421 seed = (seed << 8) | cupsFileGetChar(fp);
422 seed = (seed << 8) | cupsFileGetChar(fp);
423 CUPS_SRAND((seed << 8) | cupsFileGetChar(fp));
427 #endif /* !HAVE_ARC4RANDOM */
430 * Create a root certificate and return...
434 cupsdAddCert(0, "root", cupsdDefaultAuthType());
439 * End of "$Id: cert.c 11173 2013-07-23 12:31:34Z msweet $".