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

Revision 15187, 8.7 KB checked in by ghudson, 24 years ago (diff)
I must have typo'd applying the patch in the last rev. Fix.
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.20 2000-10-14 17:46:53 ghudson 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 <netinet/in.h>
41#include <sys/stat.h>
42#include <netdb.h>
43#include <errno.h>
44#include <pwd.h>
45#include <string.h>
46#ifdef KERBEROS
47#include <krb.h>
48#endif
49#include <discuss/tfile.h>
50#include "rpc.h"
51#include <discuss/types.h>
52#include "config.h"
53
54#define SUCCESS 1
55#define ERROR   -1
56#define min(a, b) (a < b ? a : b)
57
58/* global */
59#ifdef KERBEROS
60char rpc_caller[MAX_K_NAME_SZ + 1];
61#else
62char rpc_caller[50];
63#endif
64static long hostaddr;
65
66extern int numprocs;
67extern struct proc_table procs [];
68extern char *malloc();
69extern int errno;
70#ifdef KERBEROS
71static char serv_name[20];
72extern int krb_err_base;
73#endif /* KERBEROS */
74short recvshort();
75int rpc_err;
76extern tfile net_tfile ();
77
78/* Static variables */
79
80/* connections & socket info */
81static USPStream *us = NULL;
82
83/*
84 *
85 * init_rpc () -- Initialize the RPC mechanism
86 *
87 */
88init_rpc (service,code)
89    char *service;
90    int *code;
91{
92#ifdef INETD
93    int d;
94#endif
95    int snew;                   /* socket we're reading from */
96   
97#ifdef SUBPROC
98    int uid;
99    struct passwd *pwent;
100#endif
101   
102#ifndef ASSOC
103    struct protoent *pe;
104    struct servent *se;
105    struct sockaddr_in sai;
106    int sock_len = sizeof (sai);
107    int s;
108#endif
109   
110#ifdef KERBEROS
111    int fromlen,i;
112    struct sockaddr_in from;
113    char hostname[50];
114    struct hostent *hp;
115    USPCardinal bt;
116#endif   
117
118    init_rpc_err_tbl();
119
120#ifdef INETD
121    d = open ("/dev/null", 2);
122    dup2(d, 1);
123    dup2(d, 2);
124    close(d);
125    if (geteuid() == 0)
126        panic ("Can't run as root."); /* just in case setuid bit off */
127#endif
128   
129#ifdef ASSOC
130    /* safety check -- 0 better be a socket, not a pipe or file */
131    {
132        if (isatty (0)) {
133            *code = RPC_NOT_SUBPROC;
134            return;
135        }
136    }
137
138#ifdef SUBPROC
139    {
140        int s;
141        for (s = 1; s < 10; s++)
142            (void) close (s);
143    }
144    {
145        int fd;
146        fd = open("/dev/null", 2);
147        if (fd != 1) {
148            (void) dup2 (fd, 1);
149            (void) close (fd);
150        }
151        (void) dup2(1, 2);
152    }
153    {
154        setpgrp(0, getpid());           /* So we don't get tty signals */
155    }
156#endif
157   
158    snew = 0;
159    us = USP_associate (snew);
160#else   
161    /* to be added */
162    setprotoent(0);                         /* get protocol information */
163    pe = getprotobyname("tcp");
164    setservent(0);                          /* get service information */
165   
166    if((se = getservbyname("discuss", "tcp")) == NULL) {
167        *code = RPC_SERV_UNKNOWN;
168        return;
169    }
170    sai.sin_addr.s_addr = INADDR_ANY;
171    sai.sin_port = se->s_port;              /* set up socket */
172    if((s = socket(AF_INET, SOCK_STREAM, pe->p_proto)) < 0) {
173        *code = errno;
174        return;
175    }
176    if(bind(s, (struct sockaddr *)&sai, sizeof(sai))) {  /* bind service name */
177        *code = errno;
178        return;
179    }   
180    listen(s, SOMAXCONN);               /* listen for connection */
181    if((snew = accept(s, (struct sockaddr *)&sai, &sock_len)) < 0) {
182                                        /* accept connection */
183        *code = errno;
184        return;
185    }
186   
187    us = USP_associate (snew);
188    if (us == NULL) {
189        *code = errno;
190        return;
191    }
192#endif
193   
194    strcpy (rpc_caller, "???");         /* safety drop */
195   
196#ifdef SUBPROC
197    uid = getuid ();
198    pwent = getpwuid(uid);
199    if (pwent != 0) {
200        strcpy (rpc_caller, pwent -> pw_name);
201    }
202#endif
203    strcat (rpc_caller, "@");
204    strcat (rpc_caller, REALM);
205   
206#ifdef KERBEROS
207
208    strcpy(serv_name, service);
209    fromlen = sizeof (from);
210    if (getpeername (snew, (struct sockaddr *)&from, &fromlen) < 0) {
211        *code = errno;
212        return;
213    }
214    if (fromlen == 0) {         /* no len, UNIX domain = me */
215        gethostname(hostname, sizeof(hostname));
216        hp = gethostbyname(hostname);
217        memcpy(&hostaddr, hp -> h_addr,  4);
218    } else {
219        memcpy(&hostaddr, &from.sin_addr, 4);
220    }
221
222   
223    if ((USP_rcv_blk(us, &bt) != SUCCESS) || (bt != KRB_TICKET &&
224                                              bt != KRB_TICKET2)) {
225        *code = RPC_PROTOCOL;
226        return;
227    }
228   
229    handle_kerberos(bt,serv_name,hostaddr);
230#endif
231    *code = 0;
232    return;
233}
234
235#ifdef KERBEROS
236handle_kerberos(bt,service,haddr)
237USPCardinal bt;
238char *service;
239long haddr;
240{
241    int i,result;
242    char hostname[50];
243    char filename[50];
244    char instance[INST_SZ];
245    char *envvar;
246    AUTH_DAT kdata;
247    KTEXT_ST ticket;
248
249    strcpy (rpc_caller, "???@");                /* safety drop */
250    strcat (rpc_caller, REALM);
251
252    /* read authenticator off net */
253    ticket.length = recvshort();
254    if ((ticket.length<=0) || (ticket.length>MAX_KTXT_LEN)) {
255        result = RPC_PROTOCOL;
256        goto punt_kerberos;
257    }
258    for (i=0; i<ticket.length; i++) {
259        ticket.dat[i] = recvshort();
260    }
261   
262    envvar = malloc(strlen(service) + 50);
263    if (envvar) {
264        sprintf(envvar, "KRB5_KTNAME=/var/spool/%s/krb5.keytab", service);
265        putenv(envvar);
266    }
267
268    /* make filename from service */
269    strcpy (filename, "/var/spool/");
270    strcat (filename, service);
271    strcat (filename, "/srvtab");
272   
273    strcpy(instance,"*");
274    result = krb_rd_req (&ticket, service, instance, haddr, &kdata, filename);
275    if (result == 0) {
276        strcpy(rpc_caller, kdata.pname);
277        if (kdata.pinst[0] != '\0') {
278            strcat(rpc_caller, ".");
279            strcat(rpc_caller, kdata.pinst);
280        }
281        strcat(rpc_caller, "@");
282        strcat(rpc_caller, kdata.prealm);
283    }
284    else {
285        result += krb_err_base;
286        goto punt_kerberos;
287    }
288punt_kerberos:
289    USP_flush_block(us);
290    if (bt == KRB_TICKET2) {
291         USP_begin_block(us,TICKET_REPLY);
292         USP_put_long_integer(us, i);
293         USP_end_block(us);
294    }
295}
296#endif /* KERBEROS */
297
298/*
299 *
300 * recvit ()  -- Routine to accept an RPC call.
301 *
302 */
303recvit (code)
304    int *code;
305{
306    USPCardinal bt;
307    int procno;
308
309    if (USP_rcv_blk(us, &bt) != SUCCESS) {
310        if (errno = ECONNRESET) {               /* he went away, so do we */
311            *code = errno;
312        }
313        *code = errno;
314        return;
315    }
316
317#ifdef KERBEROS
318    if (bt == KRB_TICKET || bt == KRB_TICKET2) {
319         handle_kerberos(bt, serv_name, hostaddr);
320         *code = 0;
321         return;
322    }
323#endif /* KERBEROS */
324
325    procno = bt - PROC_BASE;
326
327    if (procno == 0) {
328        *code = RPC_PROTOCOL;
329        return;
330    }
331    if (procno > numprocs) {
332        USP_flush_block(us);
333        senddunno();
334        *code = 0;
335        return;
336    }
337
338    rpc_err = 0;
339    dispatch (procno);
340    *code = rpc_err;
341    return;
342}
343
344int recvint ()
345{
346    USPLong_integer li;
347   
348    if (USP_get_long_integer(us, &li) != SUCCESS) {
349        rpc_err = errno;
350        return(0);
351    }
352   
353    return (li);
354}
355short recvshort ()
356{
357    USPInteger li;
358   
359    if (USP_get_integer(us, &li) != SUCCESS) {
360        rpc_err = errno;
361        return(0);
362    }
363   
364    return (li);
365}
366
367/*
368 *
369 * recvstr ()  -- Receive a string from an RPC call
370 *
371 */
372char *recvstr ()
373{
374    USPString str;
375   
376    if (USP_get_string(us, &str) != SUCCESS) {
377        rpc_err = errno;
378        return("");
379    }
380   
381    return (str);
382}
383
384/*
385 *
386 * recvbool ()  -- Receive a boolean in an RPC call.
387 *
388 */
389bool recvbool()
390{
391    USPBoolean flag;
392   
393    if (USP_get_boolean(us, &flag) != SUCCESS) {
394        rpc_err = errno;
395        return(0);
396    }
397   
398    return ((bool)flag);
399}
400
401/*
402 *
403 * recvfile() -- Receive a file in an RPC call.
404 *
405 */
406tfile recvfile ()
407{
408    USPLong_integer tfs;
409    tfile tf;
410   
411    if (USP_get_long_integer(us, &tfs) != SUCCESS) {
412        rpc_err = errno;
413        return(0);
414    }
415   
416    tf = net_tfile (tfs,us);
417   
418    return (tf);
419}
420
421/*
422 *
423 * startreply()  -- Get ready to send reply of an RPC call.
424 *
425 */
426startreply()
427{
428    USP_begin_block(us,REPLY_TYPE);
429   
430    return;
431}
432
433/*
434 *
435 * sendint(i)  -- Send an integer in an RPC return.
436 *
437 */
438sendint(i)
439    int i;
440{
441    if (USP_put_long_integer(us, i) != SUCCESS) {
442        rpc_err = errno + rpc_err_base;
443    }
444}
445
446/*
447 *
448 * sendstr(i)  -- Send a string in an RPC return.
449 *
450 */
451sendstr(str)
452    char *str;
453{
454    if (str == NULL)
455      str = "";
456    if (USP_put_string(us, str) != SUCCESS) {
457        rpc_err = rpc_err_base + errno;
458        return;
459    }
460}
461
462/*
463 *
464 * sendbool(b)  -- Send a boolean in an RPC return.
465 *
466 */
467sendbool(b)
468    bool b;
469{
470    if (USP_put_boolean(us, (USPBoolean)b) != SUCCESS) {
471        rpc_err = rpc_err_base + errno;
472        return;
473    }
474}
475
476/*
477 *
478 * sendreply () -- Make the final call.
479 *
480 */
481sendreply()
482{
483    if (USP_end_block(us) != SUCCESS) {
484        rpc_err = rpc_err_base + errno;
485        return;
486    }
487    return;
488}
489
490/*
491 *
492 * senddunno () -- Send a 'I don't know this call' reply
493 *
494 */
495senddunno()
496{
497    USP_begin_block(us,UNKNOWN_CALL);
498    if (USP_end_block(us) != SUCCESS) {
499        rpc_err = rpc_err_base + errno;
500        return;
501    }
502    return;
503}
Note: See TracBrowser for help on using the repository browser.