]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/cert.c
Load cups into easysw/current.
[thirdparty/cups.git] / scheduler / cert.c
CommitLineData
ef416fc2 1/*
e1d6a774 2 * "$Id: cert.c 5305 2006-03-18 03:05:12Z mike $"
ef416fc2 3 *
4 * Authentication certificate routines for the Common UNIX
5 * Printing System (CUPS).
6 *
bd7854cb 7 * Copyright 1997-2006 by Easy Software Products.
ef416fc2 8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Easy Software Products and are protected by Federal
11 * copyright law. Distribution and use rights are outlined in the file
12 * "LICENSE.txt" which should have been included with this file. If this
13 * file is missing or damaged please contact Easy Software Products
14 * at:
15 *
16 * Attn: CUPS Licensing Information
17 * Easy Software Products
18 * 44141 Airport View Drive, Suite 204
19 * Hollywood, Maryland 20636 USA
20 *
21 * Voice: (301) 373-9600
22 * EMail: cups-info@cups.org
23 * WWW: http://www.cups.org
24 *
25 * Contents:
26 *
27 * cupsdAddCert() - Add a certificate.
28 * cupsdDeleteCert() - Delete a single certificate.
29 * cupsdDeleteAllCerts() - Delete all certificates...
30 * cupsdFindCert() - Find a certificate.
31 * cupsdInitCerts() - Initialize the certificate "system" and root
32 * certificate.
33 */
34
35/*
36 * Include necessary headers...
37 */
38
39#include "cupsd.h"
fa73b229 40#ifdef HAVE_ACL_INIT
41# include <sys/acl.h>
bd7854cb 42# ifdef HAVE_MEMBERSHIP_H
43# include <membership.h>
44# endif /* HAVE_MEMBERSHIP_H */
fa73b229 45#endif /* HAVE_ACL_INIT */
ef416fc2 46
47
48/*
49 * 'cupsdAddCert()' - Add a certificate.
50 */
51
52void
53cupsdAddCert(int pid, /* I - Process ID */
54 const char *username) /* I - Username */
55{
56 int i; /* Looping var */
57 cupsd_cert_t *cert; /* Current certificate */
58 int fd; /* Certificate file */
59 char filename[1024]; /* Certificate filename */
60 static const char hex[] = "0123456789ABCDEF";
61 /* Hex constants... */
62
63
64 cupsdLogMessage(CUPSD_LOG_DEBUG2,
65 "cupsdAddCert: adding certificate for pid %d", pid);
66
67 /*
68 * Allocate memory for the certificate...
69 */
70
71 if ((cert = calloc(sizeof(cupsd_cert_t), 1)) == NULL)
72 return;
73
74 /*
75 * Fill in the certificate information...
76 */
77
78 cert->pid = pid;
79 strlcpy(cert->username, username, sizeof(cert->username));
80
81 for (i = 0; i < 32; i ++)
82 cert->certificate[i] = hex[random() & 15];
83
84 /*
85 * Save the certificate to a file readable only by the User and Group
86 * (or root and SystemGroup for PID == 0)...
87 */
88
89 snprintf(filename, sizeof(filename), "%s/certs/%d", StateDir, pid);
90 unlink(filename);
91
92 if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400)) < 0)
93 {
94 cupsdLogMessage(CUPSD_LOG_ERROR,
95 "cupsdAddCert: Unable to create certificate file %s - %s",
96 filename, strerror(errno));
97 free(cert);
98 return;
99 }
100
101 if (pid == 0)
102 {
fa73b229 103#ifdef HAVE_ACL_INIT
104 acl_t acl; /* ACL information */
105 acl_entry_t entry; /* ACL entry */
106 acl_permset_t permset; /* Permissions */
bd7854cb 107# ifdef HAVE_MBR_UID_TO_UUID
fa73b229 108 uuid_t group; /* Group ID */
bd7854cb 109# endif /* HAVE_MBR_UID_TO_UUID */
fa73b229 110#endif /* HAVE_ACL_INIT */
111
112
ef416fc2 113 /*
114 * Root certificate...
115 */
116
117 fchmod(fd, 0440);
118 fchown(fd, RunUser, SystemGroupIDs[0]);
119
bd7854cb 120 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddCert: NumSystemGroups=%d",
121 NumSystemGroups);
122
fa73b229 123#ifdef HAVE_ACL_INIT
124 if (NumSystemGroups > 1)
125 {
126 /*
127 * Set POSIX ACLs for the root certificate so that all system
128 * groups can access it...
129 */
130
bd7854cb 131# ifdef HAVE_MBR_UID_TO_UUID
132 /*
133 * On MacOS X, ACLs use UUIDs instead of GIDs...
134 */
135
fa73b229 136 acl = acl_init(NumSystemGroups - 1);
137
138 for (i = 1; i < NumSystemGroups; i ++)
139 {
140 /*
141 * Add each group ID to the ACL...
142 */
143
144 acl_create_entry(&acl, &entry);
145 acl_get_permset(entry, &permset);
146 acl_add_perm(permset, ACL_READ_DATA);
147 acl_set_tag_type(entry, ACL_EXTENDED_ALLOW);
148 mbr_gid_to_uuid((gid_t)SystemGroupIDs[i], group);
149 acl_set_qualifier(entry, &group);
150 acl_set_permset(entry, permset);
151 }
bd7854cb 152# else
153 /*
154 * POSIX ACLs need permissions for owner, group, other, and mask
155 * in addition to the rest of the system groups...
156 */
157
158 acl = acl_init(NumSystemGroups + 3);
159
160 /* Owner */
161 acl_create_entry(&acl, &entry);
162 acl_get_permset(entry, &permset);
163 acl_add_perm(permset, ACL_READ);
164 acl_set_tag_type(entry, ACL_USER_OBJ);
165 acl_set_permset(entry, permset);
166
167 /* Group */
168 acl_create_entry(&acl, &entry);
169 acl_get_permset(entry, &permset);
170 acl_add_perm(permset, ACL_READ);
171 acl_set_tag_type(entry, ACL_GROUP_OBJ);
172 acl_set_permset(entry, permset);
173
174 /* Others */
175 acl_create_entry(&acl, &entry);
176 acl_get_permset(entry, &permset);
4744bd90 177 acl_add_perm(permset, 0);
bd7854cb 178 acl_set_tag_type(entry, ACL_OTHER);
179 acl_set_permset(entry, permset);
180
181 /* Mask */
182 acl_create_entry(&acl, &entry);
183 acl_get_permset(entry, &permset);
184 acl_add_perm(permset, ACL_READ);
185 acl_set_tag_type(entry, ACL_MASK);
186 acl_set_permset(entry, permset);
187
188 for (i = 1; i < NumSystemGroups; i ++)
189 {
190 /*
191 * Add each group ID to the ACL...
192 */
193
194 acl_create_entry(&acl, &entry);
195 acl_get_permset(entry, &permset);
196 acl_add_perm(permset, ACL_READ);
197 acl_set_tag_type(entry, ACL_GROUP);
198 acl_set_qualifier(entry, SystemGroupIDs + i);
199 acl_set_permset(entry, permset);
200 }
201
202 if (acl_valid(acl))
203 {
204 char *text, *textptr;
205
206 cupsdLogMessage(CUPSD_LOG_ERROR, "ACL did not validate: %s",
207 strerror(errno));
208 text = acl_to_text(acl, NULL);
209 for (textptr = strchr(text, '\n');
210 textptr;
211 textptr = strchr(textptr + 1, '\n'))
212 *textptr = ',';
213
214 cupsdLogMessage(CUPSD_LOG_ERROR, "ACL: %s", text);
215 free(text);
216 }
217# endif /* HAVE_MBR_UID_TO_UUID */
fa73b229 218
219 if (acl_set_fd(fd, acl))
220 cupsdLogMessage(CUPSD_LOG_ERROR,
221 "Unable to set ACLs on root certificate \"%s\" - %s",
222 filename, strerror(errno));
223 acl_free(acl);
224 }
225#endif /* HAVE_ACL_INIT */
226
ef416fc2 227 RootCertTime = time(NULL);
228 }
229 else
230 {
231 /*
232 * CGI certificate...
233 */
234
235 fchmod(fd, 0400);
236 fchown(fd, User, Group);
237 }
238
239 DEBUG_printf(("ADD pid=%d, username=%s, cert=%s\n", pid, username,
240 cert->certificate));
241
242 write(fd, cert->certificate, strlen(cert->certificate));
243 close(fd);
244
245 /*
246 * Insert the certificate at the front of the list...
247 */
248
249 cert->next = Certs;
250 Certs = cert;
251}
252
253
254/*
255 * 'cupsdDeleteCert()' - Delete a single certificate.
256 */
257
258void
259cupsdDeleteCert(int pid) /* I - Process ID */
260{
261 cupsd_cert_t *cert, /* Current certificate */
262 *prev; /* Previous certificate */
263 char filename[1024]; /* Certificate file */
264
265
266 for (prev = NULL, cert = Certs; cert != NULL; prev = cert, cert = cert->next)
267 if (cert->pid == pid)
268 {
269 /*
270 * Remove this certificate from the list...
271 */
272
273 cupsdLogMessage(CUPSD_LOG_DEBUG2,
274 "cupsdDeleteCert: removing certificate for pid %d", pid);
275
276 DEBUG_printf(("DELETE pid=%d, username=%s, cert=%s\n", cert->pid,
277 cert->username, cert->certificate));
278
279 if (prev == NULL)
280 Certs = cert->next;
281 else
282 prev->next = cert->next;
283
284 free(cert);
285
286 /*
287 * Delete the file and return...
288 */
289
290 snprintf(filename, sizeof(filename), "%s/certs/%d", StateDir, pid);
291 if (unlink(filename))
292 cupsdLogMessage(CUPSD_LOG_ERROR,
293 "cupsdDeleteCert: Unable to remove %s!\n", filename);
294
295 return;
296 }
297}
298
299
300/*
301 * 'cupsdDeleteAllCerts()' - Delete all certificates...
302 */
303
304void
305cupsdDeleteAllCerts(void)
306{
307 cupsd_cert_t *cert, /* Current certificate */
308 *next; /* Next certificate */
309 char filename[1024]; /* Certificate file */
310
311
312 /*
313 * Loop through each certificate, deleting them...
314 */
315
316 for (cert = Certs; cert != NULL; cert = next)
317 {
318 /*
319 * Delete the file...
320 */
321
322 snprintf(filename, sizeof(filename), "%s/certs/%d", StateDir, cert->pid);
323 if (unlink(filename))
324 cupsdLogMessage(CUPSD_LOG_ERROR,
325 "cupsdDeleteAllCerts: Unable to remove %s!\n", filename);
326
327 /*
328 * Free memory...
329 */
330
331 next = cert->next;
332 free(cert);
333 }
334
e1d6a774 335 Certs = NULL;
336 RootCertTime = 0;
ef416fc2 337}
338
339
340/*
341 * 'cupsdFindCert()' - Find a certificate.
342 */
343
344const char * /* O - Matching username or NULL */
345cupsdFindCert(const char *certificate) /* I - Certificate */
346{
347 cupsd_cert_t *cert; /* Current certificate */
348
349
350 DEBUG_printf(("cupsdFindCert(certificate=%s)\n", certificate));
351 for (cert = Certs; cert != NULL; cert = cert->next)
352 if (!strcasecmp(certificate, cert->certificate))
353 {
354 DEBUG_printf((" returning %s...\n", cert->username));
355 return (cert->username);
356 }
357
358 DEBUG_puts(" certificate not found!");
359
360 return (NULL);
361}
362
363
364/*
365 * 'cupsdInitCerts()' - Initialize the certificate "system" and root
366 * certificate.
367 */
368
369void
370cupsdInitCerts(void)
371{
372 cups_file_t *fp; /* /dev/random file */
373 unsigned seed; /* Seed for random number generator */
374 struct timeval tod; /* Time of day */
375
376
377 /*
378 * Initialize the random number generator using the random device or
379 * the current time, as available...
380 */
381
382 if ((fp = cupsFileOpen("/dev/urandom", "rb")) == NULL)
383 {
384 /*
385 * Get the time in usecs and use it as the initial seed...
386 */
387
388 gettimeofday(&tod, NULL);
389
390 seed = (unsigned)(tod.tv_sec + tod.tv_usec);
391 }
392 else
393 {
394 /*
395 * Read 4 random characters from the random device and use
396 * them as the seed...
397 */
398
399 seed = cupsFileGetChar(fp);
400 seed = (seed << 8) | cupsFileGetChar(fp);
401 seed = (seed << 8) | cupsFileGetChar(fp);
402 seed = (seed << 8) | cupsFileGetChar(fp);
403
404 cupsFileClose(fp);
405 }
406
407 srandom(seed);
408
409 /*
410 * Create a root certificate and return...
411 */
412
413 if (!RunUser)
414 cupsdAddCert(0, "root");
415}
416
417
418/*
e1d6a774 419 * End of "$Id: cert.c 5305 2006-03-18 03:05:12Z mike $".
ef416fc2 420 */