Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / RCS / kclient.c,v
1 head    1.2;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
6
7
8 1.2
9 date    92.01.31.22.37.24;      author jromine; state Exp;
10 branches;
11 next    1.1;
12
13 1.1
14 date    92.01.31.22.37.02;      author jromine; state Exp;
15 branches;
16 next    ;
17
18
19 desc
20 @@
21
22
23 1.2
24 log
25 @*** empty log message ***
26 @
27 text
28 @/* kclient.c - connect to a server via knetd, kerberos authenticated */
29 #ifndef lint
30 static char ident[]= "$Id: kclient.c,v 1.1 1992/01/31 22:37:02 jromine Exp jromine $";
31 #endif lint
32
33
34 #include "../h/strings.h"
35 #include <stdio.h>
36 #ifdef KPOP
37 #include "../zotnet/mts/mts.h"
38 #else
39 #include "mts.h"
40 #endif
41 #include <errno.h>
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <netinet/in.h>
45 #include <netdb.h>
46 #include <arpa/inet.h>
47 #ifdef KPOP
48 #include <krb.h>
49 #include <ctype.h>
50
51 static CREDENTIALS cred;
52 static MSG_DAT msg_data;
53 static KTEXT ticket = (KTEXT)NULL;
54 static Key_schedule schedule;
55 #endif
56
57 #define NOTOK   (-1)
58 #define OK      0
59 #define DONE    1
60
61 #define TRUE    1
62 #define FALSE   0
63
64 #define OOPS1   (-2)
65 #define OOPS2   (-3)
66
67 #define MAXARGS         1000
68 #define MAXNETS         5
69 #define MAXHOSTS        25
70
71 /* \f */
72
73 extern int errno;
74 extern int  sys_nerr;
75 extern char *sys_errlist[];
76
77 struct addrent {
78     int     a_addrtype;         /* assumes AF_INET for inet_netof () */
79
80     union {
81         int     un_net;
82         char    un_addr[14];
83     } un;
84 #define a_net   un.un_net
85 #define a_addr  un.un_addr
86 };
87
88 static struct addrent *ne, *nz;
89 static struct addrent nets[MAXNETS];
90
91 static struct addrent *he, *hz;
92 static struct addrent hosts[MAXHOSTS];
93
94 #ifdef KPOP
95
96 char realservice[] = "kpop";
97
98 char krb_realm[REALM_SZ];
99 char *PrincipalHostname();
100
101 /* redefine routine names for kerberos to make the loader happy */
102 #define client kclient
103 #define rcaux krcaux
104
105 #ifdef __STDC__
106 static int rcaux (struct servent *, struct hostent *, int, char *, char *);
107 static int getport (int, int, char *);
108 static int inet (struct hostent *, int);
109 #else
110 static int rcaux (), getport (), inet ();
111 #endif /* STDC */
112 static int brkany ();
113
114 #endif /* KPOP */
115
116 char *getcpy (), **brkstring (), **copyip ();
117
118 /* \f */
119
120 int     client (args, protocol, service, rproto, response)
121 char   *args,
122        *protocol,
123        *service,
124        *response;
125 int     rproto;
126 {
127     int     sd;
128     register char **ap;
129     char   *arguments[MAXARGS];
130     register struct hostent *hp;
131 #ifndef BIND
132     register struct netent *np;
133 #endif
134     register struct servent *sp;
135 #ifndef KPOP
136 #define realservice service
137 #endif
138
139     if ((sp = getservbyname (realservice, protocol)) == NULL) {
140         (void) sprintf (response, "%s/%s: unknown service", realservice, protocol);
141         return NOTOK;
142     }
143
144     ap = arguments;
145     if (args != NULL && *args != 0)
146         ap = copyip (brkstring (getcpy (args), " ", "\n"), ap);
147     else
148         if (servers != NULL && *servers != 0)
149             ap = copyip (brkstring (getcpy (servers), " ", "\n"), ap);
150     if (ap == arguments) {
151         *ap++ = getcpy ("localhost");
152         *ap = NULL;
153     }
154
155     nz = (ne = nets) + sizeof nets / sizeof nets[0];
156     hz = (he = hosts) + sizeof hosts / sizeof hosts[0];
157
158     for (ap = arguments; *ap; ap++) {
159         if (**ap == '\01') {
160 #ifndef BIND
161             if (np = getnetbyname (*ap + 1)) {
162                 sethostent (1);
163                 while (hp = gethostent ())
164                     if (np -> n_addrtype == hp -> h_addrtype
165                             && inet (hp, np -> n_net)) {
166                         switch (sd = rcaux (sp, hp, rproto, response, service)) {
167                             case NOTOK: 
168                                 continue;
169                             case OOPS1: 
170                                 break;
171                             case OOPS2: 
172                                 return NOTOK;
173
174                             default: 
175                                 return sd;
176                         }
177                         break;
178                     }
179             }
180 #endif
181             continue;
182         }
183
184         if (hp = gethostbyname (*ap)) {
185             switch (sd = rcaux (sp, hp, rproto, response, service)) {
186                 case NOTOK: 
187                 case OOPS1: 
188                     break;
189                 case OOPS2: 
190                     return NOTOK;
191
192                 default: 
193                     return sd;
194             }
195             continue;
196         }
197     }
198
199     (void) strcpy (response, "no servers available");
200     return NOTOK;
201 }
202
203 /* \f */
204
205 static int  rcaux (sp, hp, rproto, response, service)
206 register struct servent *sp;
207 register struct hostent *hp;
208 int     rproto;
209 register char *response;
210 char *service;                          /* what they really want to talk to */
211 {
212     int     sd;
213     struct in_addr  in;
214     register struct addrent *ap;
215     struct sockaddr_in  in_socket;
216     register struct sockaddr_in *isock = &in_socket;
217 #ifdef KPOP
218     int rem;
219 #endif
220
221     for (ap = nets; ap < ne; ap++)
222         if (ap -> a_addrtype == hp -> h_addrtype && inet (hp, ap -> a_net))
223             return NOTOK;
224
225     for (ap = hosts; ap < he; ap++)
226         if (ap -> a_addrtype == hp -> h_addrtype
227                 && bcmp (ap -> a_addr, hp -> h_addr, hp -> h_length) == 0)
228             return NOTOK;
229
230     if ((sd = getport (rproto, hp -> h_addrtype, response)) == NOTOK)
231         return OOPS2;
232
233     bzero ((char *) isock, sizeof *isock);
234     isock -> sin_family = hp -> h_addrtype;
235     isock -> sin_port = sp -> s_port;
236     bcopy (hp -> h_addr, (char *) &isock -> sin_addr, hp -> h_length);
237
238     if (connect (sd, (struct sockaddr *) isock, sizeof *isock) == NOTOK)
239         switch (errno) {
240             case ENETDOWN: 
241             case ENETUNREACH: 
242                 (void) close (sd);
243                 if (ne < nz) {
244                     ne -> a_addrtype = hp -> h_addrtype;
245                     bcopy (hp -> h_addr, (char *) &in, sizeof in);
246                     ne -> a_net = inet_netof (in);
247                     ne++;
248                 }
249                 return OOPS1;
250
251             case ETIMEDOUT: 
252             case ECONNREFUSED: 
253             default: 
254                 (void) close (sd);
255                 if (he < hz) {
256                     he -> a_addrtype = hp -> h_addrtype;
257                     bcopy (hp -> h_addr, he -> a_addr, hp -> h_length);
258                     he++;
259                 }
260                 return NOTOK;
261         }
262
263 #ifdef KPOP
264     ticket = (KTEXT)malloc( sizeof(KTEXT_ST) );
265     rem = krb_sendauth(0L, sd, ticket, service, hp->h_name,
266                        (char *) krb_realmofhost(hp->h_name),
267                        (unsigned long)0, &msg_data, &cred, schedule,
268                        (struct sockaddr_in *)NULL,
269                        (struct sockaddr_in *)NULL,
270                        "KPOPV0.1");
271     if (rem != KSUCCESS) {
272         close(sd);
273         (void) strcpy(response, "Post office refused connection: ");
274         (void) strcat(response, krb_err_txt[rem]);
275         return OOPS2;
276     }
277 #endif
278
279     return sd;
280 }
281
282 /* \f */
283
284 static int getport (rproto, addrtype, response)
285 int     rproto,
286         addrtype;
287 register char *response;
288 {
289     int     sd,
290             port;
291     struct sockaddr_in  in_socket,
292                        *isock = &in_socket;
293
294     if (rproto && addrtype != AF_INET) {
295         (void) sprintf (response, "reserved ports not supported for af=%d",
296                 addrtype);
297         errno = ENOPROTOOPT;
298         return NOTOK;
299     }
300
301     if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK) {
302         (void) sprintf (response, "unable to create socket: %s",
303                 errno > 0 && errno < sys_nerr ? sys_errlist[errno]
304                 : "unknown error");
305         return NOTOK;
306     }
307 #ifdef KPOP
308     return(sd);
309 #else
310     if (!rproto)
311         return sd;
312
313     bzero ((char *) isock, sizeof *isock);
314     isock -> sin_family = addrtype;
315     for (port = IPPORT_RESERVED - 1;;) {
316         isock -> sin_port = htons ((u_short) port);
317         if (bind (sd, (struct sockaddr *) isock, sizeof *isock) != NOTOK)
318             return sd;
319
320         switch (errno) {
321             case EADDRINUSE: 
322             case EADDRNOTAVAIL: 
323                 if (--port <= IPPORT_RESERVED / 2) {
324                     (void) strcpy (response, "ports available");
325                     return NOTOK;
326                 }
327                 break;
328
329             default: 
330                 (void) sprintf (response, "unable to bind socket: %s",
331                         errno > 0 && errno < sys_nerr ? sys_errlist[errno]
332                         : "unknown error");
333                 return NOTOK;
334         }
335     }
336 #endif
337 }
338
339 /* \f */
340
341 static int  inet (hp, net)
342 register struct hostent *hp;
343 int     net;
344 {
345     struct in_addr  in;
346
347     bcopy (hp -> h_addr, (char *) &in, sizeof in);
348     return (inet_netof (in) == net);
349 }
350
351 /* \f */
352
353 /* static copies of three MH subroutines... (sigh) */
354
355 static char *broken[MAXARGS + 1];
356
357
358 static char **brkstring (strg, brksep, brkterm)
359 register char  *strg;
360 register char  *brksep,
361                *brkterm;
362 {
363     register int    bi;
364     register char   c,
365                    *sp;
366
367     sp = strg;
368
369     for (bi = 0; bi < MAXARGS; bi++) {
370         while (brkany (c = *sp, brksep))
371             *sp++ = 0;
372         if (!c || brkany (c, brkterm)) {
373             *sp = 0;
374             broken[bi] = 0;
375             return broken;
376         }
377
378         broken[bi] = sp;
379         while ((c = *++sp) && !brkany (c, brksep) && !brkany (c, brkterm))
380             continue;
381     }
382     broken[MAXARGS] = 0;
383
384     return broken;
385 }
386
387
388 static  brkany (chr, strg)
389 register char   chr,
390                *strg;
391 {
392     register char  *sp;
393
394     if (strg)
395         for (sp = strg; *sp; sp++)
396             if (chr == *sp)
397                 return 1;
398     return 0;
399 }
400
401
402 static char **copyip (p, q)
403 register char **p,
404               **q;
405 {
406     while (*p)
407         *q++ = *p++;
408     *q = 0;
409
410     return q;
411 }
412
413
414 static char *getcpy (str)
415 register char  *str;
416 {
417     register char  *cp;
418
419     if ((cp = malloc ((unsigned) (strlen (str) + 1))) == NULL)
420         return NULL;
421
422     (void) strcpy (cp, str);
423     return cp;
424 }
425 @
426
427
428 1.1
429 log
430 @Initial revision
431 @
432 text
433 @d1 1
434 a1 5
435 /*
436  *      $Source: /paris/source/4.3/new/mh.6.6/support/pop/RCS/kclient.c,v $
437  *      $Header: /paris/source/4.3/new/mh.6.6/support/pop/RCS/kclient.c,v 1.2 89/11/11 03:35:14 probe Exp $
438  */
439
440 d3 1
441 a3 1
442 static char ident[]= "$Id: /paris/source/4.3/new/mh.6.6/support/pop/RCS/kclient.c,v 1.2 89/11/11 03:35:14 probe Exp $";
443 a5 1
444 /* kclient.c - connect to a server via knetd, kerberos authenticated */
445 @