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

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