Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libcs/csauth.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1990-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* Glenn Fowler
23
* AT&T Research
24
*
25
* authenticate fd given service authentication path
26
* if path==0 then it is requested from server
27
* otherwise if fd>=0 then state->host and state->flags are assumed valid
28
* only used by tcp streams
29
* fd<0 for remote authentication on fd 0,1
30
*
31
* csauth(state,fd,path,arg) called by csopen()
32
* csauth(state,-1,path,arg) called by `cs -O...'
33
* csauth(state,fd,0,arg) normal user call
34
*/
35
36
#include "cslib.h"
37
38
#include <error.h>
39
40
#define AUTH_BASE 1000
41
42
int
43
csauth(register Cs_t* state, int fd, const char* path, const char* arg)
44
{
45
register char* s;
46
register char* t;
47
char* b;
48
char* key = 0;
49
int n;
50
int m;
51
int wfd;
52
unsigned long t1;
53
unsigned long t2;
54
struct stat st;
55
char num[64];
56
char buf[PATH_MAX + 1];
57
char tmp[PATH_MAX + 1];
58
59
static int auth = -1;
60
61
messagef((state->id, NiL, -8, "auth(%d,%s,%s) call", fd, path, arg));
62
if (!path)
63
{
64
if (fd < 0)
65
goto sorry;
66
if (!getauth(fd, n))
67
goto ok;
68
n = sfsprintf(buf, sizeof(buf), "%d\n", CS_KEY_SEND);
69
if (cswrite(state, fd, buf, n) != n)
70
{
71
messagef((state->id, NiL, -1, "auth: `%-.*s': KEY_SEND write error", n - 1, buf));
72
goto sorry;
73
}
74
if ((n = csread(state, fd, buf, sizeof(buf), CS_LINE)) <= 1)
75
{
76
messagef((state->id, NiL, -1, "auth: KEY_SEND read error"));
77
goto sorry;
78
}
79
buf[n - 1] = 0;
80
path = (const char*)buf;
81
}
82
if (stat(path, &st))
83
{
84
if (errno == ENOENT)
85
goto ok;
86
messagef((state->id, NiL, -1, "auth: %s: stat error", path));
87
return -1;
88
}
89
if (fd < 0)
90
{
91
/*
92
* the remote side of remote authentication
93
*/
94
95
fd = 0;
96
wfd = 1;
97
}
98
else wfd = fd;
99
m = getpid();
100
s = tmp + sfsprintf(tmp, sizeof(tmp) - 1, "%lu %d", (unsigned long)st.st_mtime, m);
101
if ((t = (char*)arg) && !(st.st_mode & S_IXOTH))
102
{
103
b = tmp + sizeof(tmp) - 1;
104
if (s < b)
105
{
106
*s++ = ' ';
107
while (s < b && *t)
108
if ((*s++ = *t++) == '/' && *t == '#' && *++t != '#')
109
*(s - 1) = ' ';
110
}
111
}
112
*s++ = '\n';
113
n = s - tmp;
114
if (cswrite(state, wfd, tmp, n) != n)
115
{
116
messagef((state->id, NiL, -1, "auth: `%-.*s': key write error", n - 1, tmp));
117
goto sorry;
118
}
119
if (csread(state, fd, num, sizeof(num), CS_LINE) <= 0)
120
{
121
messagef((state->id, NiL, -1, "auth: key read error"));
122
goto sorry;
123
}
124
if (*num != '\n')
125
{
126
n = 0;
127
if (state->addr == csaddr(state, NiL)) b = tmp + sfsprintf(tmp, sizeof(tmp), "%s/AUTH.%05d.", csvar(state, CS_VAR_LOCAL, 0), m);
128
else
129
{
130
s = (char*)path + strlen(path);
131
while (s > (char*)path)
132
if (*--s == '/' && ++n >= 4) break;
133
if (n != 4) goto sorry;
134
b = tmp + sfsprintf(tmp, sizeof(tmp), "%-.*s/AUTH.%05d.", s - path, path, m);
135
}
136
if (s = strrchr(tmp, '/'))
137
{
138
*s = 0;
139
if (eaccess(tmp, X_OK) && (mkdir(tmp, S_IRWXU|S_IRWXG|S_IRWXO) || chmod(tmp, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)))
140
{
141
messagef((state->id, NiL, -1, "auth: %s: challenge directory error", tmp));
142
goto sorry;
143
}
144
*s = '/';
145
}
146
t1 = CSTIME();
147
m += t1 + getppid();
148
t1 -= CS_STAT_DOWN;
149
if (auth < 0) auth = (unsigned int)CSTOSS(m, 0) % AUTH_BASE;
150
n = auth;
151
for (;;)
152
{
153
if (++auth >= AUTH_BASE) auth = 0;
154
if (auth == n)
155
{
156
messagef((state->id, NiL, -1, "auth: %s: challenge directory full", tmp));
157
goto sorry;
158
}
159
s = b + sfsprintf(b, sizeof(tmp) - (b - tmp), "%03d", auth);
160
if ((stat(tmp, &st) || t1 <= (unsigned long)st.st_ctime && !remove(tmp)) && !close(open(tmp, O_CREAT|O_TRUNC|O_cloexec, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))) break;
161
}
162
key = tmp;
163
if (tokscan(num, NiL, "%lu %lu", &t1, &t2) != 2)
164
{
165
messagef((state->id, NiL, -1, "auth: `%s': challenge syntax error", num));
166
goto sorry;
167
}
168
if (cschallenge(state, tmp, &t1, &t2))
169
goto sorry;
170
if (chmod(tmp, S_ISUID|S_ISGID|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))
171
{
172
messagef((state->id, NiL, -1, "auth: %s: challenge chmod error", tmp));
173
goto sorry;
174
}
175
t = s;
176
if (arg)
177
{
178
b = tmp + sizeof(tmp) - 1;
179
if (s < b)
180
{
181
*s++ = ' ';
182
while (s < b && *arg)
183
if ((*s++ = *arg++) == '/' && *arg == '#')
184
{
185
arg++;
186
*(s - 1) = ' ';
187
}
188
}
189
}
190
*s++ = '\n';
191
n = cswrite(state, wfd, tmp, s - tmp);
192
*t = 0;
193
if (n != s - tmp)
194
{
195
messagef((state->id, NiL, -1, "auth: `%s': ack write error", tmp));
196
goto sorry;
197
}
198
if (csread(state, fd, num, 1, CS_LINE) != 1)
199
{
200
messagef((state->id, NiL, -1, "auth: ack read error"));
201
goto sorry;
202
}
203
if (remove(tmp))
204
{
205
messagef((state->id, NiL, -1, "auth: %s: challenge remove error", tmp));
206
goto sorry;
207
}
208
}
209
if (fd >= 0) setauth(fd, n);
210
ok:
211
messagef((state->id, NiL, -8, "auth(%d,%s,%s) = 0", fd, path, arg));
212
return 0;
213
sorry:
214
if (key) remove(key);
215
errno = EACCES;
216
return -1;
217
}
218
219
/*
220
* set up the challenge {v1,v2} on path
221
*/
222
223
int
224
cschallenge(Cs_t* state, const char* path, unsigned long* v1, unsigned long* v2)
225
{
226
struct stat st;
227
228
if (touch(path, (time_t)(v1 ? *v1 : cs.time), (time_t)(v2 ? *v2 : cs.time), 0))
229
{
230
messagef((state->id, NiL, -1, "auth: %s: challenge touch error", path));
231
return -1;
232
}
233
if (stat(path, &st))
234
{
235
messagef((state->id, NiL, -1, "auth: %s: challenge stat error", path));
236
return -1;
237
}
238
if (v1)
239
*v1 = st.st_atime;
240
if (v2)
241
*v2 = st.st_mtime;
242
return 0;
243
}
244
245
int
246
_cs_auth(int fd, const char* path, const char* arg)
247
{
248
return csauth(&cs, fd, path, arg);
249
}
250
251
int
252
_cs_challenge(const char* path, unsigned long* v1, unsigned long* v2)
253
{
254
return cschallenge(&cs, path, v1, v2);
255
}
256
257