00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "eyedbconfig.h"
00025
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <sys/types.h>
00030 #include <sys/socket.h>
00031 #include <sys/stat.h>
00032 #ifdef HAVE_STROPTS_H
00033 #include <stropts.h>
00034 #endif
00035 #include <sys/uio.h>
00036 #include <sys/un.h>
00037 #include <netdb.h>
00038 #include <netinet/in.h>
00039 #include <unistd.h>
00040 #include <assert.h>
00041 #include <errno.h>
00042 #include <sys/select.h>
00043 #include <time.h>
00044
00045 #include <eyedblib/connman.h>
00046 #include <eyedblib/log.h>
00047 #include <eyedblib/rpc_lib.h>
00048 #include <lib/rpc_lib_p.h>
00049
00050 static const char *rpc_access_file;
00051
00052 typedef struct {
00053 struct in_addr addr;
00054 rpc_TcpIp tcpip;
00055 } rpc_Access;
00056
00057 #define TAKE_CHAR(S) \
00058 *p++ = 0; \
00059 words[nw++] = S; \
00060 empt = 1
00061
00062 int
00063 line_parse(FILE *fd, char buf[], char **words, int *line)
00064 {
00065 for (;;) {
00066 char *p;
00067 char c;
00068 int empt = 1;
00069 int nw = 0;
00070 int isquote = 0;
00071
00072 if (!fgets(buf, 256, fd))
00073 return -1;
00074
00075 (*line)++;
00076 p = buf;
00077
00078 while ((c = *p) == ' ' || c == '\t')
00079 p++;
00080
00081 while (c = *p) {
00082 switch(c) {
00083 case '#':
00084 if (!empt)
00085 nw++;
00086 *p++ = 0;
00087 while (c = *++p)
00088 ;
00089 break;
00090
00091 case '=':
00092 TAKE_CHAR("=");
00093 break;
00094
00095 case '!':
00096 TAKE_CHAR("!");
00097 break;
00098
00099 case '+':
00100 TAKE_CHAR("+");
00101 break;
00102
00103 case ' ':
00104 case '\t':
00105 case '\n':
00106 empt = 1;
00107 *p++ = 0;
00108 break;
00109
00110 default:
00111 if (empt) {
00112 empt = 0;
00113 words[nw++] = p;
00114 }
00115
00116 p++;
00117 break;
00118 }
00119 }
00120
00121 *p = 0;
00122 words[nw] = 0;
00123 return nw;
00124 }
00125 }
00126
00127 static int access_cnt;
00128 static rpc_Access rpc_access[512];
00129
00130 static void
00131 make_user(char *words[], int *n, rpc_User *user)
00132 {
00133 char *s = words[(*n)++];
00134
00135 if (!strcmp(s, "!"))
00136 user->mode = rpc_User::NOT;
00137 else if (!strcmp(s, "="))
00138 user->mode = rpc_User::DEF;
00139 else if (!strcmp(s, "+")) {
00140 user->mode = rpc_User::ALL;
00141 user->user = strdup("");
00142 return;
00143 }
00144 else {
00145 user->mode = rpc_User::ON;
00146 user->user = strdup(s);
00147 return;
00148 }
00149
00150 user->user = strdup(words[(*n)++]);
00151 return;
00152 }
00153
00154 static const char *
00155 get_str(int mode)
00156 {
00157 if (mode == rpc_User::ON)
00158 return "";
00159 if (mode == rpc_User::NOT)
00160 return "not ";
00161 if (mode == rpc_User::DEF)
00162 return "default=";
00163 if (mode == rpc_User::ALL)
00164 return "+";
00165 return "<unknown>";
00166 }
00167
00168 static void
00169 free_access()
00170 {
00171 int i, j;
00172 for (i = 0; i < access_cnt; i++) {
00173 for (j = 0; j < rpc_access[i].tcpip.user_cnt; j++)
00174 free(rpc_access[i].tcpip.users[j].user);
00175
00176 free(rpc_access[i].tcpip.users);
00177 }
00178 access_cnt = 0;
00179 }
00180
00181 void
00182 rpc_print_tcpip(FILE *fd, rpc_TcpIp *ci)
00183 {
00184 int j;
00185 for (j = 0; j < ci->user_cnt; j++)
00186 fprintf(fd, "%s%s%s", (j ? " " : ""), get_str(ci->users[j].mode),
00187 ci->users[j].user);
00188
00189 fprintf(fd, "\n");
00190 }
00191
00192 static int
00193 read_access_file_realize()
00194 {
00195 FILE *fd;
00196 char *words[32];
00197 int nw, i, j, u;
00198 char buf[256];
00199 int line = 0;
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 free_access();
00210
00211 if (!(fd = fopen(rpc_access_file, "r"))) {
00212 if (!hostname2addr("localhost", &rpc_access[access_cnt].addr)) {
00213 rpc_access[access_cnt].tcpip.users = (rpc_User *)calloc(sizeof(rpc_User), 1);
00214 rpc_access[access_cnt].tcpip.users[0].mode = rpc_User::ALL;
00215 rpc_access[access_cnt].tcpip.users[0].user = strdup("");
00216 rpc_access[access_cnt++].tcpip.user_cnt = 1;
00217 return 0;
00218 }
00219 return 1;
00220 }
00221
00222 while ((nw = line_parse(fd, buf, words, &line)) >= 0) {
00223 if (!nw)
00224 continue;
00225
00226 if (nw < 2) {
00227 fprintf(stderr, "access file %s: syntax error at line #%d\n",
00228 rpc_access_file, line);
00229 continue;
00230 }
00231
00232 if (!strcmp(words[0], "+"))
00233 memset(&rpc_access[access_cnt].addr, 0, sizeof(struct in_addr));
00234 else if (hostname2addr(words[0], &rpc_access[access_cnt].addr)) {
00235 fprintf(stderr, "access file %s: invalid host name at line #%d: "
00236 "%s\n", rpc_access_file, line, words[0]);
00237 continue;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247 rpc_access[access_cnt].tcpip.users = (rpc_User *)calloc((nw-1)*sizeof(rpc_User), 1);
00248 for (j = 1, u = 0; j < nw; u++)
00249 make_user(words, &j, &rpc_access[access_cnt].tcpip.users[u]);
00250
00251 rpc_access[access_cnt++].tcpip.user_cnt = u;
00252 }
00253
00254 fclose(fd);
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 return 0;
00265 }
00266
00267 static int
00268 read_access_file()
00269 {
00270 static time_t last_read;
00271
00272 int r;
00273
00274 if (!rpc_access_file)
00275 return 0;
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 r = read_access_file_realize();
00288 time(&last_read);
00289 return r;
00290 }
00291
00292 int
00293 rpc_connman_init(const char *access_file)
00294 {
00295 rpc_access_file = access_file;
00296 return read_access_file();
00297 }
00298
00299 static bool
00300 rpc_is_localhost(const struct in_addr *peer_addr)
00301 {
00302 struct in_addr addr;
00303 if (hostname2addr("localhost", &addr))
00304 return false;
00305
00306 return cmp_addr(peer_addr, &addr);
00307 }
00308
00309 rpc_ConnInfo *
00310 rpc_check_addr(struct in_addr *addr)
00311 {
00312 int i;
00313 if (read_access_file())
00314 return 0;
00315
00316 for (i = 0; i < access_cnt; i++) {
00317 if (cmp_addr(&rpc_access[i].addr, addr)) {
00318 rpc_ConnInfo *ci = (rpc_ConnInfo *)calloc(sizeof(rpc_ConnInfo), 1);
00319 ci->tcpip = rpc_access[i].tcpip;
00320 ci->peer_addr = *addr;
00321 ci->is_localhost = rpc_is_localhost(&ci->peer_addr);;
00322 return ci;
00323 }
00324 }
00325
00326 IDB_LOG(IDB_LOG_CONN,
00327 ("connection refused to %d.%d.%d.%d\n", RPC_BYTE1(addr), RPC_BYTE2(addr), RPC_BYTE3(addr), RPC_BYTE4(addr)));
00328
00329 return 0;
00330 }
00331
00332 rpc_ConnInfo *
00333 rpc_make_tcpip_conninfo(int fd)
00334 {
00335 struct sockaddr_in addr;
00336 socklen_t len = sizeof(addr);
00337
00338 memset(&addr, 0, sizeof(addr));
00339
00340 if (getpeername(fd, (struct sockaddr *)&addr, &len)) {
00341 perror("getpeername");
00342 return (rpc_ConnInfo *)0;
00343 }
00344
00345 rpc_ConnInfo *ci = rpc_check_addr(&addr.sin_addr);
00346 if (ci)
00347 ci->mode = rpc_ConnInfo::TCPIP;
00348 return ci;
00349 }
00350
00351 static rpc_ConnInfo *
00352 rpc_check_localhost(struct in_addr *addr)
00353 {
00354 if (hostname2addr("localhost", addr))
00355 return 0;
00356
00357 return rpc_check_addr(addr);
00358 }
00359
00360 #ifdef HAVE_FATTACH
00361 rpc_ConnInfo *
00362 rpc_make_stream_conninfo(int fd, struct strrecvfd *info)
00363 {
00364 struct in_addr addr;
00365 rpc_ConnInfo *ci = rpc_check_localhost(&addr);
00366
00367 if (ci) {
00368 ci->mode = rpc_ConnInfo::STREAM;
00369 ci->auth.uid = info->uid;
00370 ci->auth.gid = info->gid;
00371 ci->peer_addr = addr;
00372 ci->is_localhost = rpc_is_localhost(&ci->peer_addr);;
00373 }
00374
00375 return ci;
00376 }
00377
00378 #else
00379
00380 rpc_ConnInfo *
00381 rpc_make_unix_conninfo(int fd)
00382 {
00383 struct in_addr addr;
00384 rpc_ConnInfo *ci = rpc_check_localhost(&addr);
00385
00386 if (ci) {
00387 ci->mode = rpc_ConnInfo::UNIX;
00388 ci->peer_addr = addr;
00389 ci->is_localhost = rpc_is_localhost(&ci->peer_addr);;
00390 }
00391
00392 return ci;
00393 }
00394
00395 #endif
00396