Page MenuHomePhorge

ptloader.c
No OneTemporary

Authored By
Unknown
Size
13 KB
Referenced Files
None
Subscribers
None

ptloader.c

/* ptloader.c -- AFS group loader daemon
*
* Copyright 1996-1998, Carnegie Mellon University. All Rights Reserved.
*
* This software is made available for academic and research
* purposes only. No commercial license is hereby granted.
* Copying and other reproduction is authorized only for research,
* education, and other non-commercial purposes. No warranties,
* either expressed or implied, are made regarding the operation,
* use, or results of the software. Such a release does not permit
* use of the code for commercial purposes or benefits by anyone
* without specific, additional permission by the owner of the code.
*
*/
static char rcsid[] = "$Id: ptloader.c,v 1.15 1999/08/09 21:07:54 leg Exp $";
#include <string.h>
#include "auth_krb_pts.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <krb.h>
#include <rx/rxkad.h>
#include <afs/auth.h>
#include <com_err.h>
/* blame transarc i've been told */
#ifndef AFSCONF_CLIENTNAME
#include <afs/dirpath.h>
#define AFSCONF_CLIENTNAME AFSDIR_CLIENT_ETC_DIRPATH
#endif
static char ptclient_debug = 0;
static void newclient();
static int reauth();
int fatal();
int
key_to_key(user,instance,realm,passwd,key)
char *user, *instance, *realm, *passwd;
C_Block key;
{
memcpy(key, passwd, sizeof(des_cblock));
return (0);
}
#define AUTH_USER "postman"
#define AUTH_INTERVAL (60*60*10) /* every 10 hours*/
int
main(argc, argv)
int argc;
char *argv[];
{
int s, c, r, len;
int opt;
struct sockaddr_un srvaddr;
struct sockaddr_un clientaddr;
char fnamebuf[1024];
mode_t oldumask;
int listen_queue = 5;
extern char *optarg;
char *user;
char *pw_file = NULL;
time_t next_auth_time;
unsigned int auth_interval;
int do_reauth = 1, use_srvtab = 0;
int use_newpag = 0;
auth_interval = AUTH_INTERVAL;
user = AUTH_USER;
/* normally LOCAL6, but do this while we're logging keys */
openlog(PTCLIENT, LOG_PID, LOG_LOCAL7);
syslog(LOG_NOTICE, "starting: $Id: ptloader.c,v 1.15 1999/08/09 21:07:54 leg Exp $");
while ((opt = getopt(argc, argv, "Uspd:l:f:u:t:")) != EOF) {
switch (opt) {
case 'U':
do_reauth = 0;
break;
case 's':
use_srvtab = 1;
break;
case 'p':
use_newpag = 1;
break;
case 'd':
ptclient_debug = atoi(optarg);
if (ptclient_debug < 1) {
ptclient_debug = 1;
}
break;
case 'l':
listen_queue = atoi(optarg);
break;
case 'f':
pw_file = optarg;
break;
case 'u':
user = optarg;
break;
case 't':
auth_interval = atoi(optarg);
break;
case '?':
fprintf(stderr,"usage: -Udlfut"
"\n\t-d <n>\tdebug level"
"\n\t-l <n>\tlisten(2) queue backlog"
"\n\t-U\tDo not reauthenticate"
"\n\t-s\tAssume file is srvtab"
"\n\t-u <userid>\tuser to authenticate as"
"\n\t-f <file>\tfile for the users password"
"\n\t-t <seconds>\tinterval between authentications"
"\n\t-p\tset a new pag"
"\n");
syslog(LOG_ERR, "Invalid command line option specified");
exit(-1);
break;
default:
break;
/* just pass through */
}
}
if (listen_queue < 5) {
if (ptclient_debug) {
syslog(LOG_ERR, "Invalid listen_queue specified (%d), resetting to 5",
listen_queue);
listen_queue = 5;
}
}
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s == -1) {
syslog(LOG_ERR, "socket: %m");
exit(1);
}
strcpy(fnamebuf, STATEDIR);
strcat(fnamebuf, PTS_DBSOCKET);
(void) unlink(fnamebuf);
memset((char *)&srvaddr, 0, sizeof(srvaddr));
srvaddr.sun_family = AF_UNIX;
strcpy(srvaddr.sun_path, fnamebuf);
/* Most Unixen make sockets 777 by default
Not Linux, not DUX. */
oldumask = umask((mode_t) 0); /* for Linux */
r = bind(s, (struct sockaddr *)&srvaddr, sizeof(srvaddr));
umask(oldumask); /* for Linux */
chmod(fnamebuf, 0777); /* for DUX */
if (r == -1) {
syslog(LOG_ERR, "bind: %s: %m", fnamebuf);
exit(1);
}
r = listen(s, listen_queue);
if (r == -1) {
syslog(LOG_ERR, "listen: %m");
exit(1);
}
if (do_reauth) {
if (pw_file == NULL) {
syslog(LOG_ERR, "Invalid password file specified. Exiting...");
exit(-1);
}
if (reauth(user, pw_file, use_newpag, use_srvtab) < 0) {
syslog(LOG_ERR, "initialization failed. exiting...");
exit(-1);
}
next_auth_time = time(0) + auth_interval;
if (ptclient_debug > 10) {
syslog(LOG_DEBUG, "Authenticated as %s; next reauth at %d",
user, next_auth_time);
}
}
len = sizeof(clientaddr);
for (;;) {
c = accept(s, (struct sockaddr *)&clientaddr, &len);
if (c == -1) {
syslog(LOG_WARNING, "WARNING: accept: %m");
continue;
}
if (do_reauth && (time(0) > next_auth_time)) {
if (ptclient_debug > 10) {
syslog(LOG_DEBUG, "Reauthenticating at %d", time(0));
}
if (reauth(user, pw_file, use_newpag, use_srvtab) < 0) {
syslog(LOG_ERR, "error reauthenticating. continuing...");
} else {
next_auth_time = time(0) + auth_interval;
if (ptclient_debug) {
syslog(LOG_DEBUG, "Successfully re-authenticated.");
}
}
}
newclient(c);
}
/*NOTREACHED*/
}
static void
newclient(c)
int c;
{
char fnamebuf[1024];
char keyinhex[512];
const char *reply;
HASHINFO info;
DB *ptdb;
char indata[PTS_DB_KEYSIZE];
char user[PR_MAXNAMELEN];
namelist groups;
int i,fd,rc;
DBT key,dataheader,datalist;
ptluser us;
char (*list)[][PR_MAXNAMELEN];
size_t size;
(void)memset(&size, 0, sizeof(size));
if (read(c, &size, sizeof(size_t)) < 0) {
syslog(LOG_ERR, "socket (size): %m");
reply = "Error reading request (size)";
goto sendreply;
}
if (size > PTS_DB_KEYSIZE) {
syslog(LOG_ERR, "size sent %d is greater than buffer size %d",
size, PTS_DB_KEYSIZE);
reply = "Error: invalid request size";
goto sendreply;
}
(void)memset(&indata,0,PTS_DB_KEYSIZE);
if (read(c, &indata, size) < 0) {
syslog(LOG_ERR,"socket (indata; size = %d): %m", size);
reply = "Error reading request (key)";
goto sendreply;
}
for (i=0; i<size; i++)
sprintf(keyinhex+(2*i), "%.2x", indata[i]);
(void)memset(&user, 0, sizeof(user));
if (read(c, &user, PR_MAXNAMELEN) < 0) {
syslog(LOG_ERR, "socket(user; size = %d; key = %s): %m", size, keyinhex);
reply = "Error reading request (user)";
goto sendreply;
}
if (ptclient_debug) {
syslog(LOG_DEBUG, "user %s, cacheid %s", user, keyinhex);
}
(void)memset(&info, 0, sizeof(info));
(void)memset(&groups, 0, sizeof(groups));
groups.namelist_len = 0;
groups.namelist_val = NULL;
if ((rc = pr_ListMembers(user, &groups))) {
syslog(LOG_ERR, "pr_ListMembers %s: %s", user, error_message(rc));
reply = error_message(rc);
goto sendreply;
}
(void)memset(&key, 0, sizeof(key));
key.data = indata;
key.size = size;
us.ngroups = groups.namelist_len;
us.cached = time(0);
/* store group list in contiguous array for easy storage in the database */
list = (char (*)[][PR_MAXNAMELEN])xmalloc(us.ngroups*PR_MAXNAMELEN);
memset(list, 0, us.ngroups * PR_MAXNAMELEN);
for (i=0; i<us.ngroups; i++){
strcpy((*list)[i], groups.namelist_val[i]);
/* don't free groups.namelist_val[i]. Something else currently
* takes care of that data.
*/
}
if (groups.namelist_val != NULL) {
free(groups.namelist_val);
}
/* build and store a header record for this user */
strcpy(us.user, user);
(void)memset(&dataheader, 0, sizeof(dataheader));
dataheader.data = &us;
dataheader.size = sizeof(ptluser);
datalist.data = list;
datalist.size = us.ngroups*PR_MAXNAMELEN;
indata[PTS_DB_HOFFSET] = 'H';
strcpy(fnamebuf, STATEDIR);
strcat(fnamebuf, PTS_DBLOCK);
fd=open(fnamebuf, O_CREAT|O_TRUNC|O_RDWR, 0664);
if (fd == -1) {
syslog(LOG_ERR, "IOERROR: creating lock file %s: %m", fnamebuf);
reply="Couldn't create lock file";
free(list);
goto sendreply;
}
if (lock_blocking(fd) < 0) {
syslog(LOG_ERR, "IOERROR: locking lock file %s: %m", fnamebuf);
reply="Couldn't lock database";
free(list);
goto sendreply;
}
strcpy(fnamebuf, STATEDIR);
strcat(fnamebuf, PTS_DBFIL);
ptdb=dbopen(fnamebuf, O_RDWR, 0, DB_HASH, &info);
if (ptdb == NULL) {
syslog(LOG_ERR, "IOERROR: opening database %s: %m", fnamebuf);
close(fd);
reply="Couldn't open database";
free(list);
goto sendreply;
}
if (ptclient_debug > 10) {
for (i=0; i<size; i++)
sprintf(keyinhex+(2*i), "%.2x", indata[i]);
syslog(LOG_DEBUG, "user %s: header key: %s", user, keyinhex);
}
rc=PUT(ptdb, &key, &dataheader, 0);
if (rc < 0) {
syslog(LOG_ERR, "IOERROR: writing header into database %s: %m", fnamebuf);
CLOSE(ptdb);
close(fd);
reply="Couldn't write database";
free(list);
goto sendreply;
}
/* store the grouplist */
indata[PTS_DB_HOFFSET] = 'D';
if (ptclient_debug > 10) {
for (i=0; i<size; i++)
sprintf(keyinhex+(2*i), "%.2x", indata[i]);
syslog(LOG_DEBUG, "user %s: grouplist key: %s", user, keyinhex);
}
rc=PUT(ptdb, &key, &datalist, 0);
if (rc < 0) {
syslog(LOG_ERR, "IOERROR: writing data into database %s: %m", fnamebuf);
/* We don't do any cleanup as this is the last function in line.
* if we actually exit here, don't forget to clean up. */
}
CLOSE(ptdb);
close(fd);
/* and we're done */
free(list);
reply="OK";
sendreply:
if (retry_write(c, reply, strlen(reply)) <0) {
syslog(LOG_WARNING, "retry_write: %m");
}
close(c);
}
static int
reauth(name, file, newpag, is_srvtab)
char *name;
char *file;
int newpag;
int is_srvtab;
{
int rc;
char *reason;
char password[256];
char *c;
FILE *fp;
static char pr_init = 0;
if (pr_init) {
#ifdef HAVE_PR_END
/* this doesn't really do anything other than attempt to
* clean up the ubik connection. Calling pr_Initialize
* later in the code will most likely leak memory until
* the AFS libraries get cleaned up.
*/
pr_End();
#else
/* this destroys existing ubik connections... */
pr_Initialize(1L,"/", 0);
if (!pr_Initialize (1L, AFSCONF_CLIENTNAME, 0))
#endif
}
if (is_srvtab) {
/* Not done yet */
char lrealm[REALM_SZ];
int bkvno = 0, kerrno;
C_Block use_as_key;
CREDENTIALS c;
struct ktc_principal aserver;
struct ktc_principal aclient;
struct ktc_token atoken, btoken;
if (newpag)
setpag();
if ((kerrno = krb_get_lrealm(lrealm, 1)) != 0) {
syslog(LOG_ERR, "krb_get_lrealm: %d", kerrno);
return(-1);
}
(void)memset(password, 0, sizeof(password));
kerrno = read_service_key(name, "", lrealm, bkvno, file, (char *)password);
if (kerrno != 0) {
syslog(LOG_ERR, "read_service_key: %d", kerrno);
return(-1);
}
(void)memcpy(use_as_key, password, 8);
kerrno = krb_get_in_tkt(name, "", lrealm, "krbtgt", lrealm,
DEFAULT_TKT_LIFE, key_to_key, NULL, use_as_key);
(void)memset(use_as_key, 0, sizeof(use_as_key));
if (kerrno != 0) {
syslog(LOG_ERR, "get_in_tkt: %d", kerrno);
return(-1);
}
if ((kerrno = krb_get_cred("afs", "", lrealm, &c)) != 0) {
if ((kerrno = get_ad_tkt("afs", "", lrealm, 255)) != 0) {
syslog(LOG_ERR,"get_ad_tkt: %d", kerrno);
return(-1);
} else {
if ((kerrno = krb_get_cred("afs", "", lrealm, &c)) != 0) {
syslog(LOG_ERR,"get_cred: %d", kerrno);
return(-1);
}
}
}
strncpy(aserver.name, "afs", MAXKTCNAMELEN - 1);
strncpy(aserver.instance, "", MAXKTCNAMELEN - 1);
strncpy(aserver.cell, lrealm, MAXKTCREALMLEN - 1);
{
char *t = aserver.cell;
char *s = aserver.cell;
int c;
while (c = *t++) {
if (isupper(c)) c=tolower(c);
*s++ = c;
}
*s++ = 0;
}
atoken.kvno = c.kvno;
atoken.startTime = c.issue_date;
#ifdef HAVE_KRB_LIFE_TO_TIME
atoken.endTime = krb_life_to_time(c.issue_date, c.lifetime);
#else
atoken.endTime = c.issue_date + ((unsigned char)c.lifetime * 5 * 60);
#endif
memcpy(&atoken.sessionKey, c.session, 8);
atoken.ticketLen = c.ticket_st.length;
memcpy(atoken.ticket, c.ticket_st.dat, atoken.ticketLen);
if ((kerrno = ktc_SetToken(&aserver, &atoken, &aclient)) != 0) {
syslog(LOG_ERR, "ktc_SetToken: %d", kerrno);
return(-1);
}
} else { /* not using srvtab but using a regular file */
if ((fp = fopen(file, "r")) == NULL) {
syslog(LOG_ERR, "fopen: password file: %m");
return(-1);
}
if (fgets(password, sizeof(password), fp) == NULL) {
syslog(LOG_ERR, "fgets: unable to read password: %m");
return(-1);
}
if (feof(fp) != 0) {
syslog(LOG_ERR, "internal error: password longer than max length(%d)\n",
sizeof(password));
return(-1);
}
fclose(fp);
/* if the file has an ending \n, nuke it. */
if ((c = strrchr(password, '\n')) != NULL) {
*c='\0';
}
/* so we probably should allow instances but it isn't worth
* the overhead right now
*/
if (ka_UserAuthenticate(name, /*inst*/ "", /*realm*/0, password,
newpag, &reason))
{
syslog(LOG_ERR, "Unable to authenticate to AFS: %s", reason);
return (-1);
}
(void)memset(&password, 0, sizeof(password));
}
if ((rc = pr_Initialize(1L, AFSCONF_CLIENTNAME, 0))) {
syslog(LOG_ERR, "pr_Initialize: %s", error_message(rc));
return (-1);
}
pr_init = 1;
return 0;
}
/* we need to have this function here 'cause libcyrus.a
* makes calls to this function.
*/
int
fatal(msg, exitcode)
char *msg;
int exitcode;
{
syslog(LOG_ERR, "%s", msg);
exit(-1);
}
/* $Header: /mnt/data/cyrus/cvsroot/src/cyrus/ptclient/ptloader.c,v 1.15 1999/08/09 21:07:54 leg Exp $ */

File Metadata

Mime Type
text/x-c
Expires
Fri, Apr 24, 1:24 PM (1 d, 11 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18851340
Default Alt Text
ptloader.c (13 KB)

Event Timeline