Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F120835999
ptloader.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
13 KB
Referenced Files
None
Subscribers
None
ptloader.c
View Options
/* 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>
\t
debug level"
"
\n\t
-l <n>
\t
listen(2) queue backlog"
"
\n\t
-U
\t
Do not reauthenticate"
"
\n\t
-s
\t
Assume file is srvtab"
"
\n\t
-u <userid>
\t
user to authenticate as"
"
\n\t
-f <file>
\t
file for the users password"
"
\n\t
-t <seconds>
\t
interval between authentications"
"
\n\t
-p
\t
set 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
Details
Attached
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)
Attached To
Mode
R111 cyrus-imapd
Attached
Detach File
Event Timeline