death to trailing whitespace
[openafs.git] / src / sgistuff / ta-rauth.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * This code is used for application programs who want to transfer a
12  * token from the local system to the remote system.
13  */
14 #include <afsconfig.h>
15 #include <afs/param.h>
16
17
18 #include <sys/types.h>
19 #include <sys/param.h>
20 #include <sys/stat.h>
21 #include <sys/ioctl.h>
22 #include <sys/socket.h>
23 #include <sys/file.h>
24 #include <sys/wait.h>
25 #include <sys/time.h>
26
27 #include <netinet/in.h>
28
29 #include <afs/auth.h>
30 #include <afs/cellconfig.h>
31
32 #include <stdio.h>
33 #include <ctype.h>
34 #include <signal.h>
35 #include <strings.h>
36 #if defined(AIX)
37 #include <sys/syslog.h>
38 #else /* defined(AIX) */
39 #include <syslog.h>
40 #endif /* defined(AIX) */
41 #include <errno.h>
42 #include <pwd.h>
43 #include <afs/afsutil.h>
44
45
46 #ifndef RAUTH_PORT
47 #define RAUTH_PORT (601)
48 #endif
49
50  /* ta_rauth provides a single entry point into the remote */
51  /* authentication scheme.  This allows us to simply pass the service */
52  /* name; this routine will in turn obtain whatever remote */
53  /* authentication information necessary and will negotiate with the */
54  /* remote connection.  There are three possible return codes: */
55  /*  (0) There is no remote authentication system; continue without */
56  /*      any authentication. */
57  /*  (1) Remote authentication was negotiated successfully */
58  /*  (-1) Remote authentication failed (but did exist) */
59  /*  (-2) The call could not complete due to internal failure */
60  /*  (-3) The remote connection failed */
61  /* Note that raddr is in *network* byte order! */
62
63 int ta_debug = 0;
64
65 int
66 ta_rauth(s, svc_name, raddr)
67      int s;
68      char *svc_name;
69      struct in_addr raddr;
70 {
71     char localName[64];
72     int code;
73     struct afsconf_dir *tdir;
74     struct ktc_principal tserver;
75     struct ktc_token token;
76     struct sockaddr_in name;
77
78     /* extract the token */
79
80     tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
81     if (!tdir) {
82         if (ta_debug) {
83             syslog(LOG_ERR, "ta_rauth: afsconf_Open failed\n");
84         }
85         return (-2);
86     }
87     code = afsconf_GetLocalCell(tdir, localName, sizeof(localName));
88     if (code) {
89         if (ta_debug) {
90             syslog(LOG_ERR, "ta_rauth: afsconf_GetLocalCell failed\n");
91         }
92         return (-2);
93     }
94     afsconf_Close(tdir);
95
96     strcpy(tserver.cell, localName);
97     strcpy(tserver.name, "afs");
98
99     code = ktc_GetToken(&tserver, &token, sizeof(token), NULL);
100     if (code) {
101         syslog(LOG_WARNING, "ta_rauth: no tokens available");
102         return 0;               /* try port without authentication */
103     }
104
105     name.sin_family = AF_INET;
106     name.sin_port = htons(RAUTH_PORT);
107     name.sin_addr = raddr;
108     if (connect(s, (struct sockaddr *)&name, sizeof(name)) == -1) {
109         extern int errno;
110
111         if (ta_debug) {
112             syslog(LOG_ERR,
113                    "ta_rauth(%s): connect call to (%d:%d) failed=%d\n",
114                    svc_name, raddr.s_addr, htons(RAUTH_PORT), errno);
115             perror("socket");
116         }
117         switch (errno) {
118 #ifdef AFS_AIX_ENV
119             /* On conn failure aix doesn't return any error! */
120         case 0:
121 #endif
122         case ECONNREFUSED:
123             return 0;
124         case ETIMEDOUT:
125         case ENETUNREACH:
126             return -3;
127         default:
128             return -2;
129         }
130     }
131
132     if (outtoken(s, &token, svc_name, localName) == 0) {
133         char result;
134
135         if (read(s, &result, 1) != 1) {
136             syslog(LOG_ERR, "Invalid return from remote authenticator\n");
137             exit(1);
138         }
139         if (result == '0')      /* remote authentication denied */
140             return -1;
141         else                    /* remote authentication allowed */
142             return 1;
143     }
144
145     return (-2);
146 }
147
148 /*
149  * outtoken:
150  *
151  * This routine writes a token on the specified file handle;
152  * The output format for a token is:
153  *
154  *   Field #    Contents         description
155  *    (0)       Service requested char[]
156  *    (1)       Version #        unsigned integer (< 2^32)
157  *    (2)       startTime        unsigned afs_int32 (< 2^32)
158  *    (3)       endTime          unsigned afs_int32 (< 2^32)
159  *    (4)       sessionKey       char[8]
160  *    (5)       kvno             short (< 2^16)
161  *    (6)       ticketLen        unsigned integer (< 2^32)
162  *    (7)       ticket           char[MAXKTCTICKETLEN]
163  *
164  *  All fields are comma separated except (4) and (5) because (4) is fixed
165  *  length; since field (7) is variable length, it is presumed to
166  *  begin after the ',' and to be ticketLen afs_int32.
167  */
168 outtoken(s, token, svc, localName)
169      int s;
170      struct ktc_token *token;
171      char *svc, *localName;
172 {
173     char buf[1024], *bp;
174     int count;
175
176     /* (0) - (3) */
177     sprintf(buf, "%s,%d,%s,%ld,%ld,", svc, 2, localName, token->startTime,
178             token->endTime);
179
180     /* (4) sessionKey */
181     bp = buf + strlen(buf);
182     memcpy(bp, &token->sessionKey, 8);
183     bp += 8;
184
185     /* (5) - (6) */
186     sprintf(bp, "%u,%u,", token->kvno, token->ticketLen);
187
188     /* (7) ticket */
189     bp += strlen(bp);
190     memcpy(bp, token->ticket, token->ticketLen);
191     bp += token->ticketLen;
192
193     if ((count = write(s, buf, (int)(bp - buf))) == -1) {
194         perror("outtoken write");
195         exit(1);
196     }
197     if (ta_debug) {
198         fprintf(stderr, "sent buffer %s\n", buf);
199     }
200     return 0;
201 }