]> eyrie.org Git - kerberos/kftgt.git/blob - kftgtd.c
Fix POD syntax errors in kftgt man page
[kerberos/kftgt.git] / kftgtd.c
1 /*  $Id: kftgtd.c 2300 2005-12-22 00:29:26Z rra $
2 **
3 **  Server program for Kerberos v4 ticket forwarding.
4 */
5
6 #include "config.h"
7
8 #include <stdio.h>
9 #include <sys/types.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
13 #include <netdb.h>
14 #include <syslog.h>
15 #include <pwd.h>
16 #include <memory.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <signal.h>
20 #include <unistd.h>
21
22 #ifdef HAVE_KERBEROSIV_KRB_H
23 # include <kerberosIV/krb.h>
24 #else
25 # include <krb.h>
26 #endif
27
28 #include "kftgt.h"
29 #include "encrypt.h"
30 #include "marsh.h"
31
32 void log_init();
33 void log_close();
34 void log_and_die(char *mess);
35 void log_message(char *mess);
36 void usage();
37
38 char *prog;
39
40 int l_flag =0, d_flag = 0, v_flag=0;
41 int t_val = 60;
42
43 RETSIGTYPE 
44 timeout()
45 {
46   if (d_flag) log_message("timeout");
47   exit(1);
48 }
49
50 int
51 main(argc,argv)
52   int argc;
53   char **argv;
54 {
55   struct sockaddr_in caddr, saddr;
56   size_t    clen, slen;
57   int status;
58   KRB_INT32 authopts;
59   AUTH_DAT auth_data;
60   KTEXT_ST clt_ticket;
61   Key_schedule sched;
62   char instance[INST_SZ];
63   char version[9];
64   char lname[KFTGT_MAX_USERNAME];
65   char buffer[KFTGT_MAX_BUFFER];
66   char tkfile[KFTGT_MAX_PATHNAME];
67   struct passwd *pw;
68   MSG_DAT m_data;
69   int len;
70   CREDENTIALS tgtcred;
71
72   int c, err_flag=0;
73   extern int optind, opterr;
74   extern char *optarg;
75
76   prog = argv[0];
77
78 #ifdef HAVE_DECL_KRB_IGNORE_IP_ADDRESS
79   krb_ignore_ip_address = 1;
80 #endif
81  
82   while ((c = getopt(argc, argv, "hlvdt:")) != EOF) 
83      switch (c) {
84      case 'd':         d_flag=1;        break;
85      case 'h':         usage();         break;
86      case 't':         t_val=atoi(optarg); break;
87      case 'v':         v_flag=1;        break;
88      case 'l':         l_flag=1;        break;
89      default:
90          err_flag++;
91      }
92
93   if (t_val <0) usage();
94
95   if (v_flag) {
96     fprintf(stderr,"%s version %s\n", prog, PACKAGE_VERSION);
97     exit(0);
98   }
99
100   if (err_flag) (void)usage();
101
102   /* set alarm for timeout */
103   signal(SIGALRM, timeout);
104   alarm(t_val);
105
106   /* get address of the client */
107   clen = sizeof(caddr);
108   if (getpeername(0, (struct sockaddr *) &caddr, &clen) < 0) {
109      log_and_die("getpeername: %m");
110   }
111
112   /* get our address for mutual authentication */
113   slen = sizeof(saddr);
114   if (getsockname(0, (struct sockaddr *) &saddr, &slen) < 0) {
115      log_and_die("getsockname: %m");
116   }
117
118   /* read the authenticator */
119   strcpy(instance,"*");
120
121   authopts = KOPT_DO_MUTUAL;
122
123   status = krb_recvauth(authopts, 0, &clt_ticket, SERVICE_PRINCIPAL,
124        instance, &caddr, &saddr, &auth_data, SRVTAB, sched, version);
125   if (status != KSUCCESS) {
126       sprintf(buffer,"kftgtd krb_recvauth: %s", krb_err_txt[status]);
127       write(0,buffer,strlen(buffer)+1);
128       log_and_die(buffer);
129   }
130
131   if (strncmp(version, KFTGT_PROTO_VERSION,1) != 0) {
132       sprintf(buffer,"kftgtd: protocol version mismatch");
133       write(0,buffer,strlen(buffer)+1);
134       log_and_die(buffer);
135   }
136
137   if (write(0,"ok",3)!=3) log_and_die("write of krb_recvauth OK failed: %m");
138
139   /* read remote username and ticketfile */
140    len = receive_encrypted_chunk(&m_data,buffer,sizeof(buffer), 0,
141          &auth_data.session, sched, &caddr, &saddr);
142
143    if (len <0) log_and_die("receive_encrypted_chunk failed");
144
145    if (unmarshall_params(lname, sizeof(lname)-1, tkfile, sizeof(tkfile)-1,
146                  m_data.app_data, m_data.app_length) < 0) {
147        sprintf(buffer,"kftgtd: unable to unmarshall params");
148           send_encrypted_chunk(buffer,strlen(buffer)+1,0,
149                       &auth_data.session, sched, &saddr, &caddr); 
150           log_and_die(buffer);
151    }
152
153    if (d_flag) {
154         sprintf(buffer,"lname(%s) tkfile(%s)", lname,tkfile);
155         log_message(buffer);
156    }
157
158    unsetenv("KRBTKFILE"); /* don't inherit from inetd! */
159    krb_set_tkt_string(tkfile);
160
161    /* if user is "\0" then call krb_kntoln to get username */
162
163    if (lname[0]=='\0') { 
164    /*    if (krb_kntoln(&auth_data,lname) != KSUCCESS) { */
165        char lrealm[REALM_SZ] = "";
166        if ( (!(*lrealm) && (krb_get_lrealm(lrealm,1) == KFAILURE)) 
167           ||  strcmp(auth_data.prealm,lrealm)) {
168           sprintf(buffer,"kftgtd: unable to determine local username");
169           send_encrypted_chunk(buffer,strlen(buffer)+1,0,
170                       &auth_data.session, sched, &saddr, &caddr); 
171           exit(1);
172         }
173        (void) strcpy(lname,auth_data.pname);
174    }
175
176    /* we now have the local user in lname */
177
178    /* first lookup password entry */
179
180    if ( (pw =getpwnam(lname)) == NULL)  {
181           sprintf(buffer,"kftgtd: no password entry for %s!",lname);
182           send_encrypted_chunk(buffer,strlen(buffer)+1,0,
183                       &auth_data.session, sched, &saddr, &caddr); 
184           log_and_die(buffer);
185    }
186
187    /* now check with kuserok */
188
189    if (kuserok(&auth_data,lname) != 0) {
190           sprintf(buffer,
191                 "kftgtd: you are not allowed to forward tickets to %s",lname);
192           send_encrypted_chunk(buffer,strlen(buffer)+1,0,
193                       &auth_data.session, sched, &saddr, &caddr); 
194          log_and_die(buffer);
195    }
196
197    if (    (setgid(pw->pw_gid) != 0) 
198         || (setuid(pw->pw_uid) != 0)
199    ) {
200           sprintf(buffer,"kftgtd: process init failed");
201           send_encrypted_chunk(buffer,strlen(buffer)+1,0,
202                       &auth_data.session, sched, &saddr, &caddr); 
203           exit(1);
204    }
205
206    /* we are now running under the user's privs */
207    /* send back ok to client */
208
209    send_encrypted_chunk("ok",3,0,&auth_data.session, sched, &saddr, &caddr);
210
211    /* now read tgt */
212
213    len = receive_encrypted_chunk(&m_data,buffer,sizeof(buffer), 0,
214          &auth_data.session, sched, &caddr, &saddr);
215
216    if (len <0) log_and_die("receive_encrypted_chunk of tgt failed");
217    /* null terminate */
218    m_data.app_data[m_data.app_length] = '\0';
219
220    if (unmarshall_cred(&tgtcred, m_data.app_data, m_data.app_length) < 0) {
221           sprintf(buffer,"kftgtd: unmarshall of tgt failed");
222           send_encrypted_chunk(buffer,strlen(buffer)+1,0,
223                       &auth_data.session, sched, &saddr, &caddr); 
224           log_and_die(buffer);
225    }
226
227    /* we now have the tgt!!!!!!! */
228
229   if(d_flag) {
230      sprintf(buffer,"in_tkt(%s.%s)\n",tgtcred.pname,tgtcred.pinst);
231      log_message(buffer);
232      sprintf(buffer,"save_creds(%s.%s@%s)\n",tgtcred.service,tgtcred.instance,
233                    tgtcred.realm);
234      log_message(buffer);
235   }
236
237   /* initialize ticket cache  and stash tickets */
238     if ( 
239         ((status = in_tkt(tgtcred.pname,tgtcred.pinst)) != KSUCCESS)
240       || ((status= krb_save_credentials(
241                 tgtcred.service, tgtcred.instance, tgtcred.realm,
242                  tgtcred.session,tgtcred.lifetime,tgtcred.kvno,
243                  &tgtcred.ticket_st, tgtcred.issue_date)) != KSUCCESS)
244      ) {
245           sprintf(buffer,"kftgtd: kerberos error: %s",krb_err_txt[status]);
246           send_encrypted_chunk(buffer,strlen(buffer)+1,0,
247                       &auth_data.session, sched, &saddr, &caddr); 
248           exit(1);
249    }
250
251    send_encrypted_chunk("ok",3,0,&auth_data.session, sched, &saddr, &caddr);
252    if (l_flag) {
253       sprintf(buffer,"%s.%s@%s at %s forwarded to %s, %s",
254                auth_data.pname,
255                auth_data.pinst,
256                auth_data.prealm,
257                inet_ntoa(caddr.sin_addr),
258                lname,
259                tkt_string());
260       log_message(buffer);
261    }
262    log_close();
263    exit(0);
264 }
265
266 static int log_init_called=0;
267
268 void log_init()
269 {
270     if (log_init_called) return;
271 #ifndef LOG_DAEMON /* 4.2 syslog */
272     openlog(prog, 0);
273 #else /* 4.3 syslog */
274     openlog(prog, 0, LOG_DAEMON);
275 #endif /* 4.2 syslog */
276     log_init_called = 1;
277 }
278
279 void log_close()
280 {
281   if (log_init_called) closelog();
282 }
283
284
285 void log_and_die(char *mess)
286 {
287   log_init();
288   syslog(LOG_ERR, mess);
289   closelog();
290   exit(1);
291 }
292
293 void log_message(char *mess)
294 {
295   log_init();
296   syslog(LOG_ERR, mess);
297 }
298
299
300 void usage()
301 {
302   fprintf(stderr,"\n");
303   fprintf(stderr,"Usage: %s [options]\n",prog);
304   fprintf(stderr,"   -l          log ticket forwarding requsts\n");
305   fprintf(stderr,"   -t secs     timeout, default is 60 seconds\n");
306   fprintf(stderr,"   -v          version\n");
307   fprintf(stderr,"   -d          debug info\n");
308   fprintf(stderr,"\n");
309   exit(1);
310 }