]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/cert.c
2 * "$Id: cert.c 7673 2008-06-18 22:31:26Z mike $"
4 * Authentication certificate routines for the Common UNIX
5 * Printing System (CUPS).
7 * Copyright 2007-2008 by Apple Inc.
8 * Copyright 1997-2006 by Easy Software Products.
10 * These coded instructions, statements, and computer programs are the
11 * property of Apple Inc. and are protected by Federal copyright
12 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
13 * which should have been included with this file. If this file is
14 * file is missing or damaged, see the license at "http://www.cups.org/".
18 * cupsdAddCert() - Add a certificate.
19 * cupsdDeleteCert() - Delete a single certificate.
20 * cupsdDeleteAllCerts() - Delete all certificates...
21 * cupsdFindCert() - Find a certificate.
22 * cupsdInitCerts() - Initialize the certificate "system" and root
27 * Include necessary headers...
33 # ifdef HAVE_MEMBERSHIP_H
34 # include <membership.h>
35 # endif /* HAVE_MEMBERSHIP_H */
36 #endif /* HAVE_ACL_INIT */
40 * 'cupsdAddCert()' - Add a certificate.
44 cupsdAddCert(int pid
, /* I - Process ID */
45 const char *username
, /* I - Username */
46 void *ccache
) /* I - Kerberos credentials or NULL */
48 int i
; /* Looping var */
49 cupsd_cert_t
*cert
; /* Current certificate */
50 int fd
; /* Certificate file */
51 char filename
[1024]; /* Certificate filename */
52 static const char hex
[] = "0123456789ABCDEF";
53 /* Hex constants... */
56 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
57 "cupsdAddCert: adding certificate for pid %d", pid
);
60 * Allocate memory for the certificate...
63 if ((cert
= calloc(sizeof(cupsd_cert_t
), 1)) == NULL
)
67 * 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
[random() & 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 "cupsdAddCert: 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 # ifdef HAVE_MBR_UID_TO_UUID
127 * On MacOS X, ACLs use UUIDs instead of GIDs...
130 acl
= acl_init(NumSystemGroups
- 1);
132 for (i
= 1; i
< NumSystemGroups
; i
++)
135 * Add each group ID to the ACL...
138 acl_create_entry(&acl
, &entry
);
139 acl_get_permset(entry
, &permset
);
140 acl_add_perm(permset
, ACL_READ_DATA
);
141 acl_set_tag_type(entry
, ACL_EXTENDED_ALLOW
);
142 mbr_gid_to_uuid((gid_t
)SystemGroupIDs
[i
], group
);
143 acl_set_qualifier(entry
, &group
);
144 acl_set_permset(entry
, permset
);
148 * POSIX ACLs need permissions for owner, group, other, and mask
149 * in addition to the rest of the system groups...
152 acl
= acl_init(NumSystemGroups
+ 3);
155 acl_create_entry(&acl
, &entry
);
156 acl_get_permset(entry
, &permset
);
157 acl_add_perm(permset
, ACL_READ
);
158 acl_set_tag_type(entry
, ACL_USER_OBJ
);
159 acl_set_permset(entry
, permset
);
162 acl_create_entry(&acl
, &entry
);
163 acl_get_permset(entry
, &permset
);
164 acl_add_perm(permset
, ACL_READ
);
165 acl_set_tag_type(entry
, ACL_GROUP_OBJ
);
166 acl_set_permset(entry
, permset
);
169 acl_create_entry(&acl
, &entry
);
170 acl_get_permset(entry
, &permset
);
171 acl_add_perm(permset
, 0);
172 acl_set_tag_type(entry
, ACL_OTHER
);
173 acl_set_permset(entry
, permset
);
176 acl_create_entry(&acl
, &entry
);
177 acl_get_permset(entry
, &permset
);
178 acl_add_perm(permset
, ACL_READ
);
179 acl_set_tag_type(entry
, ACL_MASK
);
180 acl_set_permset(entry
, permset
);
182 for (i
= 1; i
< NumSystemGroups
; i
++)
185 * Add each group ID to the ACL...
188 acl_create_entry(&acl
, &entry
);
189 acl_get_permset(entry
, &permset
);
190 acl_add_perm(permset
, ACL_READ
);
191 acl_set_tag_type(entry
, ACL_GROUP
);
192 acl_set_qualifier(entry
, SystemGroupIDs
+ i
);
193 acl_set_permset(entry
, permset
);
198 char *text
, *textptr
; /* Temporary string */
201 cupsdLogMessage(CUPSD_LOG_ERROR
, "ACL did not validate: %s",
203 text
= acl_to_text(acl
, NULL
);
204 for (textptr
= strchr(text
, '\n');
206 textptr
= strchr(textptr
+ 1, '\n'))
209 cupsdLogMessage(CUPSD_LOG_ERROR
, "ACL: %s", text
);
212 # endif /* HAVE_MBR_UID_TO_UUID */
214 if (acl_set_fd(fd
, acl
))
216 if (errno
!= EOPNOTSUPP
|| !acls_not_supported
)
217 cupsdLogMessage(CUPSD_LOG_ERROR
,
218 "Unable to set ACLs on root certificate \"%s\" - %s",
219 filename
, strerror(errno
));
221 if (errno
== EOPNOTSUPP
)
222 acls_not_supported
= 1;
227 #endif /* HAVE_ACL_INIT */
229 RootCertTime
= time(NULL
);
238 fchown(fd
, User
, Group
);
241 DEBUG_printf(("ADD pid=%d, username=%s, cert=%s\n", pid
, username
,
244 write(fd
, cert
->certificate
, strlen(cert
->certificate
));
248 * Add Kerberos credentials as needed...
252 cert
->ccache
= (krb5_ccache
)ccache
;
255 #endif /* HAVE_GSSAPI */
258 * Insert the certificate at the front of the list...
267 * 'cupsdDeleteCert()' - Delete a single certificate.
271 cupsdDeleteCert(int pid
) /* I - Process ID */
273 cupsd_cert_t
*cert
, /* Current certificate */
274 *prev
; /* Previous certificate */
275 char filename
[1024]; /* Certificate file */
278 for (prev
= NULL
, cert
= Certs
; cert
!= NULL
; prev
= cert
, cert
= cert
->next
)
279 if (cert
->pid
== pid
)
282 * Remove this certificate from the list...
285 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
286 "cupsdDeleteCert: removing certificate for pid %d", pid
);
288 DEBUG_printf(("DELETE pid=%d, username=%s, cert=%s\n", cert
->pid
,
289 cert
->username
, cert
->certificate
));
294 prev
->next
= cert
->next
;
298 * Release Kerberos credentials as needed...
302 krb5_cc_destroy(KerberosContext
, cert
->ccache
);
303 #endif /* HAVE_GSSAPI */
308 * Delete the file and return...
311 snprintf(filename
, sizeof(filename
), "%s/certs/%d", StateDir
, pid
);
312 if (unlink(filename
))
313 cupsdLogMessage(CUPSD_LOG_ERROR
,
314 "cupsdDeleteCert: Unable to remove %s!", filename
);
322 * 'cupsdDeleteAllCerts()' - Delete all certificates...
326 cupsdDeleteAllCerts(void)
328 cupsd_cert_t
*cert
, /* Current certificate */
329 *next
; /* Next certificate */
330 char filename
[1024]; /* Certificate file */
334 * Loop through each certificate, deleting them...
337 for (cert
= Certs
; cert
!= NULL
; cert
= next
)
343 snprintf(filename
, sizeof(filename
), "%s/certs/%d", StateDir
, cert
->pid
);
344 if (unlink(filename
))
345 cupsdLogMessage(CUPSD_LOG_ERROR
,
346 "cupsdDeleteAllCerts: Unable to remove %s!", filename
);
362 * 'cupsdFindCert()' - Find a certificate.
365 cupsd_cert_t
* /* O - Matching certificate or NULL */
366 cupsdFindCert(const char *certificate
) /* I - Certificate */
368 cupsd_cert_t
*cert
; /* Current certificate */
371 DEBUG_printf(("cupsdFindCert(certificate=%s)\n", certificate
));
372 for (cert
= Certs
; cert
!= NULL
; cert
= cert
->next
)
373 if (!strcasecmp(certificate
, cert
->certificate
))
375 DEBUG_printf((" returning %s...\n", cert
->username
));
379 DEBUG_puts(" certificate not found!");
386 * 'cupsdInitCerts()' - Initialize the certificate "system" and root
393 cups_file_t
*fp
; /* /dev/random file */
394 unsigned seed
; /* Seed for random number generator */
395 struct timeval tod
; /* Time of day */
399 * Initialize the random number generator using the random device or
400 * the current time, as available...
403 if ((fp
= cupsFileOpen("/dev/urandom", "rb")) == NULL
)
406 * Get the time in usecs and use it as the initial seed...
409 gettimeofday(&tod
, NULL
);
411 seed
= (unsigned)(tod
.tv_sec
+ tod
.tv_usec
);
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 seed
= (seed
<< 8) | cupsFileGetChar(fp
);
431 * Create a root certificate and return...
435 cupsdAddCert(0, "root", NULL
);
440 * End of "$Id: cert.c 7673 2008-06-18 22:31:26Z mike $".