source: trunk/athena/bin/discuss/server/rpproc.c @ 23807

Revision 23807, 10.3 KB checked in by broder, 15 years ago (diff)
In discuss: * Use HAVE_KRB4 and HAVE_KRB5 instead of KERBEROS and KERBEROS5.
Line 
1/*
2 *
3 *      Copyright (C) 1988, 1989 by the Massachusetts Institute of Technology
4 *      Developed by the MIT Student Information Processing Board (SIPB).
5 *      For copying information, see the file mit-copyright.h in this release.
6 *
7 */
8/*
9 *
10 *  rpproc.c -- Procedures to implement a simple (perhaps brain-asleep) RPC
11 *              protocol over a TCP connection.
12 *              This file handles the server's side of the connection.
13 *
14 */
15
16/*
17 *
18 *      $Id: rpproc.c,v 1.23 2007-08-09 20:41:33 amb Exp $
19 *
20 */
21
22
23#ifdef INETD
24#define ASSOC 1
25#endif
26
27#ifdef SUBPROC
28#define ASSOC 1
29#endif
30
31/* Includes */
32
33#include <sys/ioctl.h>
34#if HAVE_FCNTL_H
35#include <fcntl.h>
36#endif
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <netinet/in.h>
42#include <sys/stat.h>
43#include <netdb.h>
44#include <errno.h>
45#include <pwd.h>
46#include <string.h>
47#ifdef HAVE_KRB4
48#include <krb.h>
49#endif
50#ifdef HAVE_KRB5
51#include <krb5.h>
52#endif
53#include <discuss/tfile.h>
54#include "rpc.h"
55#include <discuss/types.h>
56#include "config.h"
57
58#define SUCCESS 1
59#define ERROR   -1
60#define min(a, b) (a < b ? a : b)
61
62/* global */
63#ifdef HAVE_KRB4
64char rpc_caller[MAX_K_NAME_SZ + 1];
65#else
66char rpc_caller[50];
67#endif
68static long hostaddr;
69
70extern int numprocs;
71extern struct proc_table procs [];
72#ifdef HAVE_KRB4
73static char serv_name[20];
74#endif /* HAVE_KRB4 */
75short recvshort();
76int rpc_err;
77extern tfile net_tfile ();
78
79/* Static variables */
80
81/* connections & socket info */
82static USPStream *us = NULL;
83
84/*
85 *
86 * init_rpc () -- Initialize the RPC mechanism
87 *
88 */
89init_rpc (service,code)
90    char *service;
91    int *code;
92{
93#ifdef INETD
94    int d;
95#endif
96    int snew;                   /* socket we're reading from */
97   
98#ifdef SUBPROC
99    int uid;
100    struct passwd *pwent;
101#endif
102   
103#ifndef ASSOC
104    struct protoent *pe;
105    struct servent *se;
106    struct sockaddr_in sai;
107    int sock_len = sizeof (sai);
108    int s;
109#endif
110   
111#ifdef HAVE_KRB4
112    int fromlen,i;
113    struct sockaddr_in from;
114    char hostname[50];
115    struct hostent *hp;
116    USPCardinal bt;
117#endif   
118
119#if defined(__APPLE__) && defined(__MACH__)
120    add_error_table(&et_rpc_error_table);
121#else
122    initialize_rpc_error_table();
123#endif
124
125#ifdef INETD
126    d = open ("/dev/null", 2);
127    dup2(d, 1);
128    dup2(d, 2);
129    close(d);
130    if (geteuid() == 0)
131        panic ("Can't run as root."); /* just in case setuid bit off */
132#endif
133   
134#ifdef ASSOC
135    /* safety check -- 0 better be a socket, not a pipe or file */
136    {
137        if (isatty (0)) {
138            *code = RPC_NOT_SUBPROC;
139            return;
140        }
141    }
142
143#ifdef SUBPROC
144    {
145        int s;
146        for (s = 1; s < 10; s++)
147            (void) close (s);
148    }
149    {
150        int fd;
151        fd = open("/dev/null", 2);
152        if (fd != 1) {
153            (void) dup2 (fd, 1);
154            (void) close (fd);
155        }
156        (void) dup2(1, 2);
157    }
158    {
159        setpgrp(0, getpid());           /* So we don't get tty signals */
160    }
161#endif
162   
163    snew = 0;
164    us = USP_associate (snew);
165#else   
166    /* to be added */
167    setprotoent(0);                         /* get protocol information */
168    pe = getprotobyname("tcp");
169    setservent(0);                          /* get service information */
170   
171    se = getservbyname(SERVICE_NAME, "tcp");
172    sai.sin_addr.s_addr = INADDR_ANY;
173    sai.sin_port = (se) ? se->s_port : htons(DISCUSS_FALLBACK_PORT);
174                                            /* set up socket */
175    if((s = socket(AF_INET, SOCK_STREAM, pe->p_proto)) < 0) {
176        *code = errno;
177        return;
178    }
179    if(bind(s, (struct sockaddr *)&sai, sizeof(sai))) {  /* bind service name */
180        *code = errno;
181        return;
182    }   
183    listen(s, SOMAXCONN);               /* listen for connection */
184    if((snew = accept(s, (struct sockaddr *)&sai, &sock_len)) < 0) {
185                                        /* accept connection */
186        *code = errno;
187        return;
188    }
189   
190    us = USP_associate (snew);
191    if (us == NULL) {
192        *code = errno;
193        return;
194    }
195#endif
196   
197    strcpy (rpc_caller, "???");         /* safety drop */
198   
199#ifdef SUBPROC
200    uid = getuid ();
201    pwent = getpwuid(uid);
202    if (pwent != 0) {
203        strcpy (rpc_caller, pwent -> pw_name);
204    }
205#endif
206    strcat (rpc_caller, "@");
207    strcat (rpc_caller, REALM);
208   
209#ifdef HAVE_KRB4
210
211    strcpy(serv_name, service);
212    fromlen = sizeof (from);
213    if (getpeername (snew, (struct sockaddr *)&from, &fromlen) < 0) {
214        *code = errno;
215        return;
216    }
217    if (fromlen == 0) {         /* no len, UNIX domain = me */
218        gethostname(hostname, sizeof(hostname));
219        hp = gethostbyname(hostname);
220        memcpy(&hostaddr, hp -> h_addr,  4);
221    } else {
222        memcpy(&hostaddr, &from.sin_addr, 4);
223    }
224
225   
226    if ((USP_rcv_blk(us, &bt) != SUCCESS) || (bt != KRB_TICKET &&
227                                              bt != KRB_TICKET2)) {
228        *code = RPC_PROTOCOL;
229        return;
230    }
231   
232    handle_kerberos(bt,serv_name,hostaddr);
233#endif
234    *code = 0;
235    return;
236}
237
238#ifdef HAVE_KRB4
239handle_kerberos(bt,service,haddr)
240USPCardinal bt;
241char *service;
242long haddr;
243{
244    int i,result;
245    char hostname[50];
246    char filename[50];
247    char instance[INST_SZ];
248    AUTH_DAT kdata;
249    KTEXT_ST ticket;
250
251#ifdef HAVE_KRB5
252    char *envvar;
253    krb5_context context;
254    krb5_auth_context auth_context = NULL;
255    krb5_data packet;
256    krb5_principal sprinc;
257    krb5_keytab keytab = NULL;
258    krb5_ticket *processed_ticket = NULL;
259#endif /* HAVE_KRB5 */
260
261    strcpy (rpc_caller, "???@");                /* safety drop */
262    strcat (rpc_caller, REALM);
263
264    /* read authenticator off net */
265    ticket.length = recvshort();
266    if ((ticket.length<=0) || (ticket.length>MAX_KTXT_LEN)) {
267        result = RPC_PROTOCOL;
268        goto punt_kerberos;
269    }
270    for (i=0; i<ticket.length; i++) {
271        ticket.dat[i] = recvshort();
272    }
273#ifdef HAVE_KRB5
274    packet.length = ticket.length;
275    packet.data = (krb5_pointer) ticket.dat;
276   
277    envvar = malloc(strlen(service) + 50);
278    if (envvar) {
279        sprintf(envvar, "KRB5_KTNAME=/var/spool/%s/krb5.keytab", service);
280        putenv(envvar);
281    }
282#endif /* HAVE_KRB5 */
283    /* make filename from service */
284    strcpy (filename, "/var/spool/");
285    strcat (filename, service);
286    strcat (filename, "/srvtab");
287
288    strcpy(instance, "*");
289
290#ifdef HAVE_KRB5
291    result = krb5_init_context(&context);
292    if (result) {
293        com_err(service, result, "while initializing krb5");
294        goto punt_kerberos;
295    }
296    result = krb5_sname_to_principal(context, NULL, service, KRB5_NT_SRV_HST,
297                                     &sprinc);
298    if (result) {
299        com_err(service, result, "while generating srv name %s", service);
300        goto punt_kerberos;
301    }
302    result = krb5_rd_req(context, &auth_context, &packet, sprinc, keytab,
303                         NULL, &processed_ticket);
304    if (result == 0) {  /* It's a valid krb5 request */
305        result = krb5_524_conv_principal(context,
306                                         processed_ticket->enc_part2->client,
307                                         kdata.pname, kdata.pinst,
308                                         kdata.prealm);
309        if (result) {
310            com_err(service, result, "while converting principal to krb4");
311            goto punt_kerberos;
312        }
313    }
314    else {  /* Let's try krb4 */
315        /* First, log the krb5 error. */
316        com_err(service, result, "while reading request");
317#endif /* HAVE_KRB5 */
318        result = krb_rd_req (&ticket, service, instance, haddr, &kdata,
319                             filename);
320        if (result) {
321            result += ERROR_TABLE_BASE_krb;
322            goto punt_kerberos;
323        }
324#ifdef HAVE_KRB5
325    }
326#endif /* HAVE_KRB5 */
327
328    strcpy(rpc_caller, kdata.pname);
329    if (kdata.pinst[0] != '\0') {
330        strcat(rpc_caller, ".");
331        strcat(rpc_caller, kdata.pinst);
332    }
333    strcat(rpc_caller, "@");
334    strcat(rpc_caller, kdata.prealm);
335
336punt_kerberos:
337    USP_flush_block(us);
338    if (bt == KRB_TICKET2) {
339         USP_begin_block(us,TICKET_REPLY);
340         USP_put_long_integer(us, i);
341         USP_end_block(us);
342    }
343}
344#endif /* HAVE_KRB4 */
345
346/*
347 *
348 * recvit ()  -- Routine to accept an RPC call.
349 *
350 */
351recvit (code)
352    int *code;
353{
354    USPCardinal bt;
355    int procno;
356
357    if (USP_rcv_blk(us, &bt) != SUCCESS) {
358        if (errno == ECONNRESET) {              /* he went away, so do we */
359            *code = errno;
360        }
361        *code = errno;
362        return;
363    }
364
365#ifdef HAVE_KRB4
366    if (bt == KRB_TICKET || bt == KRB_TICKET2) {
367         handle_kerberos(bt, serv_name, hostaddr);
368         *code = 0;
369         return;
370    }
371#endif /* HAVE_KRB4 */
372
373    procno = bt - PROC_BASE;
374
375    if (procno == 0) {
376        *code = RPC_PROTOCOL;
377        return;
378    }
379    if (procno > numprocs) {
380        USP_flush_block(us);
381        senddunno();
382        *code = 0;
383        return;
384    }
385
386    rpc_err = 0;
387    dispatch (procno);
388    *code = rpc_err;
389    return;
390}
391
392int recvint ()
393{
394    USPLong_integer li;
395   
396    if (USP_get_long_integer(us, &li) != SUCCESS) {
397        rpc_err = errno;
398        return(0);
399    }
400   
401    return (li);
402}
403short recvshort ()
404{
405    USPInteger li;
406   
407    if (USP_get_integer(us, &li) != SUCCESS) {
408        rpc_err = errno;
409        return(0);
410    }
411   
412    return (li);
413}
414
415/*
416 *
417 * recvstr ()  -- Receive a string from an RPC call
418 *
419 */
420char *recvstr ()
421{
422    USPString str;
423   
424    if (USP_get_string(us, &str) != SUCCESS) {
425        rpc_err = errno;
426        return("");
427    }
428   
429    return (str);
430}
431
432/*
433 *
434 * recvbool ()  -- Receive a boolean in an RPC call.
435 *
436 */
437bool recvbool()
438{
439    USPBoolean flag;
440   
441    if (USP_get_boolean(us, &flag) != SUCCESS) {
442        rpc_err = errno;
443        return(0);
444    }
445   
446    return ((bool)flag);
447}
448
449/*
450 *
451 * recvfile() -- Receive a file in an RPC call.
452 *
453 */
454tfile recvfile ()
455{
456    USPLong_integer tfs;
457    tfile tf;
458   
459    if (USP_get_long_integer(us, &tfs) != SUCCESS) {
460        rpc_err = errno;
461        return(0);
462    }
463   
464    tf = net_tfile (tfs,us);
465   
466    return (tf);
467}
468
469/*
470 *
471 * startreply()  -- Get ready to send reply of an RPC call.
472 *
473 */
474startreply()
475{
476    USP_begin_block(us,REPLY_TYPE);
477   
478    return;
479}
480
481/*
482 *
483 * sendint(i)  -- Send an integer in an RPC return.
484 *
485 */
486sendint(i)
487    int i;
488{
489    if (USP_put_long_integer(us, i) != SUCCESS) {
490        rpc_err = errno + ERROR_TABLE_BASE_rpc;
491    }
492}
493
494/*
495 *
496 * sendstr(i)  -- Send a string in an RPC return.
497 *
498 */
499sendstr(str)
500    char *str;
501{
502    if (str == NULL)
503      str = "";
504    if (USP_put_string(us, str) != SUCCESS) {
505        rpc_err = ERROR_TABLE_BASE_rpc + errno;
506        return;
507    }
508}
509
510/*
511 *
512 * sendbool(b)  -- Send a boolean in an RPC return.
513 *
514 */
515sendbool(b)
516    bool b;
517{
518    if (USP_put_boolean(us, (USPBoolean)b) != SUCCESS) {
519        rpc_err = ERROR_TABLE_BASE_rpc + errno;
520        return;
521    }
522}
523
524/*
525 *
526 * sendreply () -- Make the final call.
527 *
528 */
529sendreply()
530{
531    if (USP_end_block(us) != SUCCESS) {
532        rpc_err = ERROR_TABLE_BASE_rpc + errno;
533        return;
534    }
535    return;
536}
537
538/*
539 *
540 * senddunno () -- Send a 'I don't know this call' reply
541 *
542 */
543senddunno()
544{
545    USP_begin_block(us,UNKNOWN_CALL);
546    if (USP_end_block(us) != SUCCESS) {
547        rpc_err = ERROR_TABLE_BASE_rpc + errno;
548        return;
549    }
550    return;
551}
Note: See TracBrowser for help on using the repository browser.