1 /* $Id: kftgtd.c 2300 2005-12-22 00:29:26Z rra $
3 ** Server program for Kerberos v4 ticket forwarding.
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
22 #ifdef HAVE_KERBEROSIV_KRB_H
23 # include <kerberosIV/krb.h>
34 void log_and_die(char *mess);
35 void log_message(char *mess);
40 int l_flag =0, d_flag = 0, v_flag=0;
46 if (d_flag) log_message("timeout");
55 struct sockaddr_in caddr, saddr;
62 char instance[INST_SZ];
64 char lname[KFTGT_MAX_USERNAME];
65 char buffer[KFTGT_MAX_BUFFER];
66 char tkfile[KFTGT_MAX_PATHNAME];
73 extern int optind, opterr;
78 #ifdef HAVE_DECL_KRB_IGNORE_IP_ADDRESS
79 krb_ignore_ip_address = 1;
82 while ((c = getopt(argc, argv, "hlvdt:")) != EOF)
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;
93 if (t_val <0) usage();
96 fprintf(stderr,"%s version %s\n", prog, PACKAGE_VERSION);
100 if (err_flag) (void)usage();
102 /* set alarm for timeout */
103 signal(SIGALRM, timeout);
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");
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");
118 /* read the authenticator */
119 strcpy(instance,"*");
121 authopts = KOPT_DO_MUTUAL;
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);
131 if (strncmp(version, KFTGT_PROTO_VERSION,1) != 0) {
132 sprintf(buffer,"kftgtd: protocol version mismatch");
133 write(0,buffer,strlen(buffer)+1);
137 if (write(0,"ok",3)!=3) log_and_die("write of krb_recvauth OK failed: %m");
139 /* read remote username and ticketfile */
140 len = receive_encrypted_chunk(&m_data,buffer,sizeof(buffer), 0,
141 &auth_data.session, sched, &caddr, &saddr);
143 if (len <0) log_and_die("receive_encrypted_chunk failed");
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);
154 sprintf(buffer,"lname(%s) tkfile(%s)", lname,tkfile);
158 unsetenv("KRBTKFILE"); /* don't inherit from inetd! */
159 krb_set_tkt_string(tkfile);
161 /* if user is "\0" then call krb_kntoln to get username */
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);
173 (void) strcpy(lname,auth_data.pname);
176 /* we now have the local user in lname */
178 /* first lookup password entry */
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);
187 /* now check with kuserok */
189 if (kuserok(&auth_data,lname) != 0) {
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);
197 if ( (setgid(pw->pw_gid) != 0)
198 || (setuid(pw->pw_uid) != 0)
200 sprintf(buffer,"kftgtd: process init failed");
201 send_encrypted_chunk(buffer,strlen(buffer)+1,0,
202 &auth_data.session, sched, &saddr, &caddr);
206 /* we are now running under the user's privs */
207 /* send back ok to client */
209 send_encrypted_chunk("ok",3,0,&auth_data.session, sched, &saddr, &caddr);
213 len = receive_encrypted_chunk(&m_data,buffer,sizeof(buffer), 0,
214 &auth_data.session, sched, &caddr, &saddr);
216 if (len <0) log_and_die("receive_encrypted_chunk of tgt failed");
218 m_data.app_data[m_data.app_length] = '\0';
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);
227 /* we now have the tgt!!!!!!! */
230 sprintf(buffer,"in_tkt(%s.%s)\n",tgtcred.pname,tgtcred.pinst);
232 sprintf(buffer,"save_creds(%s.%s@%s)\n",tgtcred.service,tgtcred.instance,
237 /* initialize ticket cache and stash tickets */
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)
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);
251 send_encrypted_chunk("ok",3,0,&auth_data.session, sched, &saddr, &caddr);
253 sprintf(buffer,"%s.%s@%s at %s forwarded to %s, %s",
257 inet_ntoa(caddr.sin_addr),
266 static int log_init_called=0;
270 if (log_init_called) return;
271 #ifndef LOG_DAEMON /* 4.2 syslog */
273 #else /* 4.3 syslog */
274 openlog(prog, 0, LOG_DAEMON);
275 #endif /* 4.2 syslog */
281 if (log_init_called) closelog();
285 void log_and_die(char *mess)
288 syslog(LOG_ERR, mess);
293 void log_message(char *mess)
296 syslog(LOG_ERR, mess);
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");