#include "cupsd.h"
#include <grp.h>
void
AddCert(int pid,
const char *username)
{
int i;
cert_t *cert;
int fd;
char filename[1024];
struct group *grp;
static const char hex[] = "0123456789ABCDEF";
LogMessage(L_DEBUG2, "AddCert: adding certificate for pid %d", pid);
if ((cert = calloc(sizeof(cert_t), 1)) == NULL)
return;
cert->pid = pid;
strlcpy(cert->username, username, sizeof(cert->username));
for (i = 0; i < 32; i ++)
cert->certificate[i] = hex[random() & 15];
snprintf(filename, sizeof(filename), "%s/certs/%d", ServerRoot, pid);
unlink(filename);
if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400)) < 0)
{
LogMessage(L_ERROR, "AddCert: Unable to create certificate file %s - %s",
filename, strerror(errno));
free(cert);
return;
}
if (pid == 0)
{
fchmod(fd, 0440);
if ((grp = getgrnam(SystemGroups[0])) == NULL)
fchown(fd, getuid(), 0);
else
fchown(fd, getuid(), grp->gr_gid);
endgrent();
RootCertTime = time(NULL);
}
else
{
fchmod(fd, 0400);
fchown(fd, User, Group);
}
DEBUG_printf(("ADD pid=%d, username=%s, cert=%s\n", pid, username,
cert->certificate));
write(fd, cert->certificate, strlen(cert->certificate));
close(fd);
cert->next = Certs;
Certs = cert;
}
void
DeleteCert(int pid)
{
cert_t *cert,
*prev;
char filename[1024];
for (prev = NULL, cert = Certs; cert != NULL; prev = cert, cert = cert->next)
if (cert->pid == pid)
{
LogMessage(L_DEBUG2, "DeleteCert: removing certificate for pid %d", pid);
DEBUG_printf(("DELETE pid=%d, username=%s, cert=%s\n", cert->pid,
cert->username, cert->certificate));
if (prev == NULL)
Certs = cert->next;
else
prev->next = cert->next;
free(cert);
snprintf(filename, sizeof(filename), "%s/certs/%d", ServerRoot, pid);
if (unlink(filename))
LogMessage(L_ERROR, "DeleteCert: Unable to remove %s!\n", filename);
return;
}
}
void
DeleteAllCerts(void)
{
cert_t *cert,
*next;
char filename[1024];
for (cert = Certs; cert != NULL; cert = next)
{
snprintf(filename, sizeof(filename), "%s/certs/%d", ServerRoot, cert->pid);
if (unlink(filename))
LogMessage(L_ERROR, "DeleteAllCerts: Unable to remove %s!\n", filename);
next = cert->next;
free(cert);
}
Certs = NULL;
}
const char *
FindCert(const char *certificate)
{
cert_t *cert;
DEBUG_printf(("FindCert(certificate=%s)\n", certificate));
for (cert = Certs; cert != NULL; cert = cert->next)
if (strcasecmp(certificate, cert->certificate) == 0)
{
DEBUG_printf((" returning %s...\n", cert->username));
return (cert->username);
}
DEBUG_puts(" certificate not found!");
return (NULL);
}
void
InitCerts(void)
{
cups_file_t *fp;
unsigned seed;
struct timeval tod;
if ((fp = cupsFileOpen("/dev/urandom", "rb")) == NULL)
{
gettimeofday(&tod, NULL);
seed = (unsigned)(tod.tv_sec + tod.tv_usec);
}
else
{
seed = cupsFileGetChar(fp);
seed = (seed << 8) | cupsFileGetChar(fp);
seed = (seed << 8) | cupsFileGetChar(fp);
seed = (seed << 8) | cupsFileGetChar(fp);
cupsFileClose(fp);
}
srandom(seed);
AddCert(0, "root");
}