]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/cert.c
2 * "$Id: cert.c 177 2006-06-21 00:20:03Z jlovell $"
4 * Authentication certificate routines for the Common UNIX
5 * Printing System (CUPS).
7 * Copyright 1997-2006 by Easy Software Products.
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
16 * Attn: CUPS Licensing Information
17 * Easy Software Products
18 * 44141 Airport View Drive, Suite 204
19 * Hollywood, Maryland 20636 USA
21 * Voice: (301) 373-9600
22 * EMail: cups-info@cups.org
23 * WWW: http://www.cups.org
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
36 * Include necessary headers...
42 # ifdef HAVE_MEMBERSHIP_H
43 # include <membership.h>
44 # endif /* HAVE_MEMBERSHIP_H */
45 #endif /* HAVE_ACL_INIT */
49 * 'cupsdAddCert()' - Add a certificate.
53 cupsdAddCert(int pid
, /* I - Process ID */
54 const char *username
) /* I - Username */
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... */
64 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
65 "cupsdAddCert: adding certificate for pid %d", pid
);
68 * Allocate memory for the certificate...
71 if ((cert
= calloc(sizeof(cupsd_cert_t
), 1)) == NULL
)
75 * Fill in the certificate information...
79 strlcpy(cert
->username
, username
, sizeof(cert
->username
));
81 for (i
= 0; i
< 32; i
++)
82 cert
->certificate
[i
] = hex
[random() & 15];
85 * Save the certificate to a file readable only by the User and Group
86 * (or root and SystemGroup for PID == 0)...
89 snprintf(filename
, sizeof(filename
), "%s/certs/%d", StateDir
, pid
);
92 if ((fd
= open(filename
, O_WRONLY
| O_CREAT
| O_EXCL
, 0400)) < 0)
94 cupsdLogMessage(CUPSD_LOG_ERROR
,
95 "cupsdAddCert: Unable to create certificate file %s - %s",
96 filename
, strerror(errno
));
104 acl_t acl
; /* ACL information */
105 acl_entry_t entry
; /* ACL entry */
106 acl_permset_t permset
; /* Permissions */
107 # ifdef HAVE_MBR_UID_TO_UUID
108 uuid_t group
; /* Group ID */
109 # endif /* HAVE_MBR_UID_TO_UUID */
110 static int acls_not_supported
= 0;
112 #endif /* HAVE_ACL_INIT */
116 * Root certificate...
120 fchown(fd
, RunUser
, SystemGroupIDs
[0]);
122 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdAddCert: NumSystemGroups=%d",
126 if (NumSystemGroups
> 1)
129 * Set POSIX ACLs for the root certificate so that all system
130 * groups can access it...
133 # ifdef HAVE_MBR_UID_TO_UUID
135 * On MacOS X, ACLs use UUIDs instead of GIDs...
138 acl
= acl_init(NumSystemGroups
- 1);
140 for (i
= 1; i
< NumSystemGroups
; i
++)
143 * Add each group ID to the ACL...
146 acl_create_entry(&acl
, &entry
);
147 acl_get_permset(entry
, &permset
);
148 acl_add_perm(permset
, ACL_READ_DATA
);
149 acl_set_tag_type(entry
, ACL_EXTENDED_ALLOW
);
150 mbr_gid_to_uuid((gid_t
)SystemGroupIDs
[i
], group
);
151 acl_set_qualifier(entry
, &group
);
152 acl_set_permset(entry
, permset
);
156 * POSIX ACLs need permissions for owner, group, other, and mask
157 * in addition to the rest of the system groups...
160 acl
= acl_init(NumSystemGroups
+ 3);
163 acl_create_entry(&acl
, &entry
);
164 acl_get_permset(entry
, &permset
);
165 acl_add_perm(permset
, ACL_READ
);
166 acl_set_tag_type(entry
, ACL_USER_OBJ
);
167 acl_set_permset(entry
, permset
);
170 acl_create_entry(&acl
, &entry
);
171 acl_get_permset(entry
, &permset
);
172 acl_add_perm(permset
, ACL_READ
);
173 acl_set_tag_type(entry
, ACL_GROUP_OBJ
);
174 acl_set_permset(entry
, permset
);
177 acl_create_entry(&acl
, &entry
);
178 acl_get_permset(entry
, &permset
);
179 acl_add_perm(permset
, 0);
180 acl_set_tag_type(entry
, ACL_OTHER
);
181 acl_set_permset(entry
, permset
);
184 acl_create_entry(&acl
, &entry
);
185 acl_get_permset(entry
, &permset
);
186 acl_add_perm(permset
, ACL_READ
);
187 acl_set_tag_type(entry
, ACL_MASK
);
188 acl_set_permset(entry
, permset
);
190 for (i
= 1; i
< NumSystemGroups
; i
++)
193 * Add each group ID to the ACL...
196 acl_create_entry(&acl
, &entry
);
197 acl_get_permset(entry
, &permset
);
198 acl_add_perm(permset
, ACL_READ
);
199 acl_set_tag_type(entry
, ACL_GROUP
);
200 acl_set_qualifier(entry
, SystemGroupIDs
+ i
);
201 acl_set_permset(entry
, permset
);
206 char *text
, *textptr
; /* Temporary string */
209 cupsdLogMessage(CUPSD_LOG_ERROR
, "ACL did not validate: %s",
211 text
= acl_to_text(acl
, NULL
);
212 for (textptr
= strchr(text
, '\n');
214 textptr
= strchr(textptr
+ 1, '\n'))
217 cupsdLogMessage(CUPSD_LOG_ERROR
, "ACL: %s", text
);
220 # endif /* HAVE_MBR_UID_TO_UUID */
222 if (acl_set_fd(fd
, acl
))
224 if (errno
!= EOPNOTSUPP
|| !acls_not_supported
)
225 cupsdLogMessage(CUPSD_LOG_ERROR
,
226 "Unable to set ACLs on root certificate \"%s\" - %s",
227 filename
, strerror(errno
));
229 if (errno
== EOPNOTSUPP
)
230 acls_not_supported
= 1;
235 #endif /* HAVE_ACL_INIT */
237 RootCertTime
= time(NULL
);
246 fchown(fd
, User
, Group
);
249 DEBUG_printf(("ADD pid=%d, username=%s, cert=%s\n", pid
, username
,
252 write(fd
, cert
->certificate
, strlen(cert
->certificate
));
256 * Insert the certificate at the front of the list...
265 * 'cupsdDeleteCert()' - Delete a single certificate.
269 cupsdDeleteCert(int pid
) /* I - Process ID */
271 cupsd_cert_t
*cert
, /* Current certificate */
272 *prev
; /* Previous certificate */
273 char filename
[1024]; /* Certificate file */
276 for (prev
= NULL
, cert
= Certs
; cert
!= NULL
; prev
= cert
, cert
= cert
->next
)
277 if (cert
->pid
== pid
)
280 * Remove this certificate from the list...
283 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
284 "cupsdDeleteCert: removing certificate for pid %d", pid
);
286 DEBUG_printf(("DELETE pid=%d, username=%s, cert=%s\n", cert
->pid
,
287 cert
->username
, cert
->certificate
));
292 prev
->next
= cert
->next
;
297 * Delete the file and return...
300 snprintf(filename
, sizeof(filename
), "%s/certs/%d", StateDir
, pid
);
301 if (unlink(filename
))
302 cupsdLogMessage(CUPSD_LOG_ERROR
,
303 "cupsdDeleteCert: Unable to remove %s!\n", filename
);
311 * 'cupsdDeleteAllCerts()' - Delete all certificates...
315 cupsdDeleteAllCerts(void)
317 cupsd_cert_t
*cert
, /* Current certificate */
318 *next
; /* Next certificate */
319 char filename
[1024]; /* Certificate file */
323 * Loop through each certificate, deleting them...
326 for (cert
= Certs
; cert
!= NULL
; cert
= next
)
332 snprintf(filename
, sizeof(filename
), "%s/certs/%d", StateDir
, cert
->pid
);
333 if (unlink(filename
))
334 cupsdLogMessage(CUPSD_LOG_ERROR
,
335 "cupsdDeleteAllCerts: Unable to remove %s!\n", filename
);
351 * 'cupsdFindCert()' - Find a certificate.
354 const char * /* O - Matching username or NULL */
355 cupsdFindCert(const char *certificate
) /* I - Certificate */
357 cupsd_cert_t
*cert
; /* Current certificate */
360 DEBUG_printf(("cupsdFindCert(certificate=%s)\n", certificate
));
361 for (cert
= Certs
; cert
!= NULL
; cert
= cert
->next
)
362 if (!strcasecmp(certificate
, cert
->certificate
))
364 DEBUG_printf((" returning %s...\n", cert
->username
));
365 return (cert
->username
);
368 DEBUG_puts(" certificate not found!");
375 * 'cupsdInitCerts()' - Initialize the certificate "system" and root
382 cups_file_t
*fp
; /* /dev/random file */
383 unsigned seed
; /* Seed for random number generator */
384 struct timeval tod
; /* Time of day */
388 * Initialize the random number generator using the random device or
389 * the current time, as available...
392 if ((fp
= cupsFileOpen("/dev/urandom", "rb")) == NULL
)
395 * Get the time in usecs and use it as the initial seed...
398 gettimeofday(&tod
, NULL
);
400 seed
= (unsigned)(tod
.tv_sec
+ tod
.tv_usec
);
405 * Read 4 random characters from the random device and use
406 * them as the seed...
409 seed
= cupsFileGetChar(fp
);
410 seed
= (seed
<< 8) | cupsFileGetChar(fp
);
411 seed
= (seed
<< 8) | cupsFileGetChar(fp
);
412 seed
= (seed
<< 8) | cupsFileGetChar(fp
);
420 * Create a root certificate and return...
424 cupsdAddCert(0, "root");
429 * End of "$Id: cert.c 177 2006-06-21 00:20:03Z jlovell $".