1// btAdd.cpp : Defines the entry point for the console application. 2// 3 4#include "FindDirectory.h" 5 6#include "betalk.h" 7#include "sysdepdefs.h" 8#include "besure_auth.h" 9#include "BlowFish.h" 10 11#include "netdb.h" 12#include "utime.h" 13#include "ctype.h" 14#include "time.h" 15#include "signal.h" 16#include "stdlib.h" 17#include "syslog.h" 18 19#define BT_MAX_THREADS 128 20#define BT_MAX_RETRIES 3 21#define BT_THREAD_NAME "BeSure Handler" 22 23typedef struct 24{ 25 unsigned int type; 26 unsigned int length; 27 char *data; 28} bt_arg_t; 29 30typedef struct session 31{ 32 int socket; 33 unsigned int client_s_addr; 34 thread_id handlerID; 35 struct session *next; 36} bt_session_t; 37 38typedef void (*bt_net_func)(bt_session_t *, unsigned int, int, bt_arg_t *); 39 40typedef struct dirCommand 41{ 42 unsigned char command; 43 bt_net_func handler; 44 bool supported; 45 uint8 args; 46 uint32 argTypes[MAX_COMMAND_ARGS]; 47} bt_command_t; 48 49 50int main(int argc, char *argv[]); 51void daemonInit(); 52void startService(); 53void endService(); 54void restartService(); 55int32 requestThread(void *data); 56int receiveRequest(bt_session_t *session); 57void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]); 58void launchThread(int client, struct sockaddr_in *addr); 59void sendErrorToClient(int client, unsigned int xid, int error); 60void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command); 61 62int btRecv(int sock, void *data, int dataLen, int flags); 63int btSend(int sock, void *data, int dataLen, int flags); 64 65void btLock(sem_id semaphore, int32 *atomic); 66void btUnlock(sem_id semaphore, int32 *atomic); 67 68int generateTicket(const char *client, const char *server, unsigned char *key, char *ticket); 69void recordLogin(char *server, char *share, char *client, bool authenticated); 70//void strlwr(char *str); 71 72int cmdAuthenticate(unsigned int addr, char *client, char *token, char *response); 73int cmdReadUsers(DIR **dir, char *user, char *fullName); 74int cmdReadGroups(DIR **dir, char *group); 75int cmdWhichGroups(DIR **dir, char *user, char *group); 76 77void netcmdAuthenticate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 78void netcmdReadUsers(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 79void netcmdReadGroups(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 80void netcmdWhichGroups(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 81void netcmdQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 82 83bt_session_t *rootSession = NULL; 84bool running = true; 85int server; 86sem_id sessionSem; 87int32 sessionVar; 88 89bt_command_t dirCommands[] = 90{ 91 { BT_CMD_AUTH, netcmdAuthenticate, true, 2, { B_STRING_TYPE, B_STRING_TYPE } }, 92 { BT_CMD_READUSERS, netcmdReadUsers, true, 1, { B_INT32_TYPE } }, 93 { BT_CMD_READGROUPS, netcmdReadGroups, true, 1, { B_INT32_TYPE } }, 94 { BT_CMD_WHICHGROUPS, netcmdWhichGroups, true, 1, { B_STRING_TYPE } }, 95 { BT_CMD_QUIT, netcmdQuit, true, 0, { 0 } }, 96 { 0, NULL, false, 0, { 0 } } 97}; 98 99 100int main(int argc, char *argv[]) 101{ 102 daemonInit(); 103 104 signal(SIGINT, endService); 105 signal(SIGTERM, endService); 106 signal(SIGHUP, restartService); 107 signal(SIGPIPE, SIG_IGN); 108 109 if ((sessionSem = create_sem(0, "Session Semaphore")) > 0) 110 { 111 // Run the daemon. We will not return until the service is being stopped. 112 startService(); 113 delete_sem(sessionSem); 114 } 115 116 return 0; 117} 118 119void daemonInit() 120{ 121 int i; 122 123 // Cause the parent task to terminate, freeing the terminal. 124 if (fork() != 0) 125 exit(0); 126 127 // In the child process, become the session leader. 128 setsid(); 129 130 // Now fork again, causing the first child to exit, since the session 131 // leader can be assigned a controlling terminal under SVR4. 132 signal(SIGHUP, SIG_IGN); 133 if (fork() != 0) 134 exit(0); 135 136 // Change to the root directory, since if we hold on to a working 137 // folder that was in a mounted file system, that file system cannot 138 // be unmounted. 139 chdir("/"); 140 141 // Reset the file creation mask to zero to eliminate the inherited value. 142 umask(0); 143 144 // Close open file descriptors. Since we can't know how many of a 145 // potentially unlimited value can be open, just close the first 64 146 // and assume that will be enough. 147 for (i = 0; i < 64; i++) 148 close(i); 149 150 // Open the syslog. 151 openlog("besure_server", LOG_PID, LOG_DAEMON); 152} 153 154void restartService() 155{ 156} 157 158void startService() 159{ 160 struct sockaddr_in serverAddr, clientAddr; 161 int client, addrLen; 162 int flags; 163 164 // Store the length of the socket addressing structure for accept(). 165 addrLen = sizeof(struct sockaddr_in); 166 167 // Initialize the server address structure. 168 memset(&serverAddr, 0, sizeof(serverAddr)); 169 serverAddr.sin_port = htons(BT_BESURE_PORT); 170 serverAddr.sin_family = AF_INET; 171 serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); 172 173 // Create a new socket to receive incoming requests. 174 server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 175 if (server == INVALID_SOCKET) 176 return; 177 178 // Set the socket option to reuse the current address in case it was 179 // in use by a prior version of the service that has not yet relinquished 180 // the socket. 181 flags = 1; 182 setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags)); 183 184 // Bind that socket to the address constructed above. 185 if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) 186 return; 187 188 // Listen for incoming connections. 189 if (listen(server, 5)) 190 return; 191 192 // Continually accept incoming connections. When one is found, 193 // fire off a handler thread to accept commands. 194 while (running) 195 { 196 client = accept(server, (struct sockaddr *) &clientAddr, &addrLen); 197 if (client != INVALID_SOCKET) 198 launchThread(client, &clientAddr); 199 } 200 201 // Close the socket. Technically, I believe we should call shutdown() 202 // first, but the BeOS header file socket.h indicates that this 203 // function is not currently working. It is present but may not have 204 // any effect. 205 shutdown(server, 2); 206 closesocket(server); 207 server = INVALID_SOCKET; 208} 209 210void endService() 211{ 212 signal(SIGINT, SIG_DFL); 213 signal(SIGTERM, SIG_DFL); 214 signal(SIGHUP, SIG_DFL); 215 signal(SIGPIPE, SIG_DFL); 216 exit(0); 217} 218 219// launchThread() 220// 221void launchThread(int client, struct sockaddr_in *addr) 222{ 223 bt_session_t *s, *cur, *last = NULL; 224 int count = 0; 225 226 // First verify that the server's not too busy by scanning the list of active 227 // sessions. This is also useful because we need to eliminate unused sessions 228 // from the list, i.e., sessions that have closed. 229 btLock(sessionSem, &sessionVar); 230 231 s = rootSession; 232 while (s) 233 { 234 if (s->socket == INVALID_SOCKET) 235 { 236 if (last) 237 last->next = s->next; 238 else 239 rootSession = s->next; 240 241 cur = s->next; 242 free(s); 243 s = cur; 244 continue; 245 } 246 247 last = s; 248 s = s->next; 249 count++; 250 } 251 252 // If the total number of valid sessions was less than our allowed maximum, then 253 // we can create a new session. 254 if (count < BT_MAX_THREADS) 255 { 256 // We need to create an available session for this connection. 257 bt_session_t *session = (bt_session_t *) malloc(sizeof(bt_session_t)); 258 if (session) 259 { 260 session->socket = client; 261 session->client_s_addr = addr->sin_addr.s_addr; 262 263 session->handlerID = 264 spawn_thread(requestThread, BT_THREAD_NAME, B_NORMAL_PRIORITY, session); 265 resume_thread(session->handlerID); 266 267 // Add this to the session list. 268 session->next = rootSession; 269 rootSession = session; 270 btUnlock(sessionSem, &sessionVar); 271 return; 272 } 273 } 274 275 btUnlock(sessionSem, &sessionVar); 276 277 // We must have too many threads active, so let the client know we're busy. 278 sendErrorToClient(client, 0, EBUSY); 279 shutdown(client, 2); 280 closesocket(client); 281} 282 283int32 requestThread(void *data) 284{ 285 bt_session_t *session = (bt_session_t *) data; 286// int flags; 287 288 if (!session) 289 return 0; 290 291// flags = 1; 292// setsockopt(server, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags)); 293 294 while (receiveRequest(session)); 295 296 shutdown(session->socket, 2); 297 closesocket(session->socket); 298 session->socket = INVALID_SOCKET; 299 return 0; 300} 301 302int receiveRequest(bt_session_t *session) 303{ 304 bt_inPacket packet; 305 char signature[20], *buffer; 306 unsigned char command; 307 int client, sigLen; 308 int32 length; 309 310 client = session->socket; 311 312 // Read the BeTalk RPC header. 313 sigLen = strlen(BT_RPC_SIGNATURE); 314 if (btRecvMsg(client, signature, sigLen, 0) == -1) 315 return 0; 316 317// recv(client, &verHi, sizeof(verHi), 0); 318// recv(client, &verLo, sizeof(verLo), 0); 319 320 signature[sigLen] = 0; 321 if (strcmp(signature, BT_RPC_SIGNATURE)) 322 return 0; 323 324 // Read in the rest of the packet. 325 if (btRecvMsg(client, &length, sizeof(int32), 0) == -1) 326 return 0; 327 328 length = B_LENDIAN_TO_HOST_INT32(length); 329 if (length == 0 || length > BT_RPC_MAX_PACKET_SIZE) 330 return 0; 331 332 buffer = (char *) malloc(length + 1); 333 if (!buffer) 334 return 0; 335 336 if (btRecvMsg(client, buffer, length, 0) == -1) 337 { 338 free(buffer); 339 return 0; 340 } 341 342 buffer[length] = 0; 343 packet.buffer = buffer; 344 packet.length = length; 345 packet.offset = 0; 346 347 // Read the transmission ID and command. 348 command = btRPCGetChar(&packet); 349 getArguments(session, &packet, command); 350 free(buffer); 351 return (command != BT_CMD_AUTH && command != BT_CMD_QUIT); 352} 353 354void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command) 355{ 356 bt_arg_t args[MAX_COMMAND_ARGS]; 357 int i, client; 358 bool error; 359 unsigned char argc, terminator; 360 int32 xid; 361 362 error = false; 363 client = session->socket; 364 argc = btRPCGetChar(packet); 365 if (argc > MAX_COMMAND_ARGS) 366 return; 367 368 for (i = 0; i < argc && !error; i++) 369 { 370 args[i].type = btRPCGetInt32(packet); 371 args[i].data = btRPCGetNewString(packet); 372 if (args[i].data == NULL) 373 error = true; 374 } 375 376 if (!error) 377 { 378 xid = btRPCGetInt32(packet); 379 terminator = btRPCGetChar(packet); 380 if (terminator == BT_CMD_TERMINATOR) 381 handleRequest(session, xid, command, argc, args); 382 } 383 else 384 sendErrorToClient(session->socket, 0, EINVAL); 385 386 while (--i >= 0) 387 free(args[i].data); 388} 389 390void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]) 391{ 392 bool validated = true; 393 int i, j; 394 395 for (i = 0; dirCommands[i].handler; i++) 396 if (command == dirCommands[i].command) 397 { 398 // We may have received a valid command, but one that is not supported by this 399 // server. In this case, we'll want to return an operation not supported error, 400 // as opposed to an invalid command error. 401 if (!dirCommands[i].supported) 402 { 403 sendErrorToClient(session->socket, xid, EOPNOTSUPP); 404 return; 405 } 406 407 // Now verify that the argument count is correct, and if so, the type of all 408 // arguments is correct. If not, an invalid command error is returned. 409 // Otherise, the command is executed, and the handler returns any necessary 410 // acknowledgement. 411 if (argc == dirCommands[i].args) 412 { 413 for (j = 0; j < argc; j++) 414 if (dirCommands[i].argTypes[j] != argv[j].type) 415 { 416 validated = false; 417 break; 418 } 419 420 if (validated) 421 { 422 (*dirCommands[i].handler)(session, xid, argc, argv); 423 return; 424 } 425 } 426 } 427 428 sendErrorToClient(session->socket, xid, EINVAL); 429} 430 431void sendErrorToClient(int client, unsigned int xid, int error) 432{ 433 bt_outPacket packet; 434 btRPCCreateAck(&packet, xid, error); 435 btRPCSendAck(client, &packet); 436} 437 438int btRecvMsg(int sock, void *data, int dataLen, int flags) 439{ 440 int bytesRead = 0; 441 do 442 { 443 int bytes = btRecv(sock, (char *) data + bytesRead, dataLen - bytesRead, flags); 444 if (bytes == -1) 445 return -1; 446 447 bytesRead += bytes; 448 } while (bytesRead < dataLen); 449 450 return bytesRead; 451} 452 453// btRecv() 454// 455int btRecv(int sock, void *data, int dataLen, int flags) 456{ 457 int bytes; 458 459 for (;;) 460 { 461 bytes = recv(sock, data, dataLen, flags); 462 if (bytes == 0) 463 return -1; 464 else if (bytes == -1) 465 if (errno == EINTR) 466 continue; 467 else 468 return -1; 469 else 470 break; 471 } 472 473 return bytes; 474} 475 476int btSendMsg(int sock, void *data, int dataLen, int flags) 477{ 478 int bytesSent = 0; 479 do 480 { 481 int bytes = btSend(sock, (char *) data + bytesSent, dataLen - bytesSent, flags); 482 if (bytes == -1) 483 return -1; 484 485 bytesSent += bytes; 486 } while (bytesSent < dataLen); 487 488 return bytesSent; 489} 490 491// btSend() 492// 493int btSend(int sock, void *data, int dataLen, int flags) 494{ 495 int bytes; 496 497 for (;;) 498 { 499 bytes = send(sock, data, dataLen, flags); 500 if (bytes == -1) 501 if (errno == EINTR) 502 continue; 503 else 504 return -1; 505 else 506 break; 507 } 508 509 return bytes; 510} 511 512void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error) 513{ 514 packet->size = BT_RPC_MIN_PACKET_SIZE; 515 packet->buffer = (char *) malloc(packet->size); 516 packet->length = 0; 517 518 if (!packet->buffer) 519 return; 520 521 strcpy(packet->buffer, BT_RPC_SIGNATURE); 522 packet->length += strlen(BT_RPC_SIGNATURE); 523 btRPCPutInt32(packet, xid); 524 btRPCPutInt32(packet, 0); 525 btRPCPutInt32(packet, error); 526} 527 528void btRPCSendAck(int client, bt_outPacket *packet) 529{ 530 if (packet) 531 if (packet->buffer) 532 { 533 *(int32 *)(&packet->buffer[9]) = B_HOST_TO_LENDIAN_INT32(packet->length - 13); 534 btSendMsg(client, packet->buffer, packet->length, 0); 535 free(packet->buffer); 536 } 537} 538 539unsigned char btRPCGetChar(bt_inPacket *packet) 540{ 541 unsigned char value; 542 543 if (packet->offset < packet->length) 544 value = (unsigned char) packet->buffer[packet->offset]; 545 else 546 value = 0; 547 548 packet->offset += sizeof(value); 549 return value; 550} 551 552unsigned int btRPCGetInt32(bt_inPacket *packet) 553{ 554 int32 value; 555 556 if (packet->offset < packet->length) 557 value = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); 558 else 559 value = 0; 560 561 packet->offset += sizeof(value); 562 return value; 563} 564 565int64 btRPCGetInt64(bt_inPacket *packet) 566{ 567 int64 value; 568 569 if (packet->offset < packet->length) 570 value = B_LENDIAN_TO_HOST_INT64(*((int64 *) &packet->buffer[packet->offset])); 571 else 572 value = 0; 573 574 packet->offset += sizeof(value); 575 return value; 576} 577 578char *btRPCGetNewString(bt_inPacket *packet) 579{ 580 char *str; 581 unsigned int bytes; 582 583 if (packet->offset >= packet->length) 584 return NULL; 585 586 bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); 587 packet->offset += sizeof(bytes); 588 if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) 589 return NULL; 590 591 str = (char *) malloc(bytes + 1); 592 if (!str) 593 return NULL; 594 595 if (bytes > 0) 596 memcpy(str, &packet->buffer[packet->offset], bytes); 597 598 str[bytes] = 0; 599 packet->offset += bytes; 600 601 return str; 602} 603 604int btRPCGetString(bt_inPacket *packet, char *buffer, int length) 605{ 606 unsigned int bytes; 607 608 if (packet->offset >= packet->length) 609 return ERANGE; 610 611 bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); 612 packet->offset += sizeof(bytes); 613 if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) 614 return ERANGE; 615 616 if (length < bytes) 617 return ERANGE; 618 619 if (bytes > 0) 620 memcpy(buffer, &packet->buffer[packet->offset], bytes); 621 622 packet->offset += bytes; 623 return bytes; 624} 625 626void btRPCGrowPacket(bt_outPacket *packet, int bytes) 627{ 628 if (packet->length + bytes > packet->size) 629 { 630 int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE; 631 packet->buffer = (char *) realloc(packet->buffer, packet->size + growth); 632 packet->size += growth; 633 } 634} 635 636void btRPCPutChar(bt_outPacket *packet, char value) 637{ 638 btRPCGrowPacket(packet, sizeof(value)); 639 packet->buffer[packet->length] = value; 640 packet->length += sizeof(value); 641} 642 643void btRPCPutInt32(bt_outPacket *packet, int32 value) 644{ 645 btRPCGrowPacket(packet, sizeof(value)); 646 *(int32 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT32(value); 647 packet->length += sizeof(value); 648} 649 650void btRPCPutInt64(bt_outPacket *packet, int64 value) 651{ 652 btRPCGrowPacket(packet, sizeof(value)); 653 *(int64 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT64(value); 654 packet->length += sizeof(value); 655} 656 657void btRPCPutString(bt_outPacket *packet, char *buffer, int length) 658{ 659 if (packet && buffer) 660 { 661 btRPCGrowPacket(packet, sizeof(length) + length); 662 btRPCPutInt32(packet, length); 663 memcpy(&packet->buffer[packet->length], buffer, length); 664 packet->length += length; 665 } 666} 667 668void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length) 669{ 670 if (packet && buffer) 671 { 672 btRPCGrowPacket(packet, length); 673 memcpy(&packet->buffer[packet->length], buffer, length); 674 packet->length += length; 675 } 676} 677 678///////////////////////////////////////////////////////////////////// 679 680void btLock(sem_id semaphore, int32 *atomic) 681{ 682 int32 previous = atomic_add(atomic, 1); 683 if (previous >= 1) 684 while (acquire_sem(semaphore) == B_INTERRUPTED); 685} 686 687void btUnlock(sem_id semaphore, int32 *atomic) 688{ 689 int32 previous = atomic_add(atomic, -1); 690 if (previous > 1) 691 release_sem(semaphore); 692} 693 694//////////////////////////////////////////////////////////////////// 695 696int generateTicket(const char *client, const char *server, unsigned char *key, char *ticket) 697{ 698 blf_ctx ctx; 699 char buffer[128], session[128]; 700 int length; 701 702 // Generate a session key. 703 sprintf(session, "%s.%s.%lx", client, server, time(NULL)); 704 705 // Generate the connection ticket. Because the ticket will be encrypted via the 706 // BlowFish algorithm, it's length must be divisible by four. We can pad the 707 // buffer with NULL characters so it won't affect the string. 708 sprintf(buffer, "%s,%s", client, session); 709 length = strlen(buffer); 710 while (length % 4) 711 buffer[length++] = ' '; 712 713 buffer[length] = 0; 714 blf_key(&ctx, key, strlen(key)); 715 blf_enc(&ctx, (unsigned long *) buffer, length / 4); 716 717 // Now we have the ticket. It gets wrapped into a response buffer here. 718 sprintf(ticket, "%s,%s,%s,%s", client, server, session, buffer); 719 return strlen(ticket); 720} 721 722// strlwr() 723/* 724void strlwr(char *str) 725{ 726 char *p; 727 for (p = str; *p; p++) 728 *p = tolower(*p); 729}*/ 730 731//////////////////////////////////////////////////////////////////// 732 733int cmdAuthenticate(unsigned int addr, char *client, char *token, char *response) 734{ 735 blf_ctx ctx; 736 char server[B_FILE_NAME_LENGTH + 1], share[B_FILE_NAME_LENGTH + 1], user[MAX_USERNAME_LENGTH + 1]; 737 char buffer[BT_AUTH_TOKEN_LENGTH * 2 + 1]; 738 unsigned char clientKey[MAX_KEY_LENGTH + 1]; 739 int i; 740 741 // Obtain the host name of our peer from the socket information. 742 struct hostent *ent = gethostbyaddr((const char *) &addr, sizeof(addr), AF_INET); 743 if (ent) 744 strcpy(server, ent->h_name); 745 else 746 { 747 uint8 *p = (uint8 *) &addr; 748 sprintf(server, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 749 } 750 751// printf("\tClient = %s\n", client); 752// printf("\tToken = %s\n", token); 753 754 // Obtain the specified client's key. 755 if (!getUserPassword(client, clientKey, sizeof(clientKey))) 756 return EACCES; 757 758// printf("\tClient key = %s\n", clientKey); 759 760 // Get the encrypted authentication information. 761 memcpy(buffer, token, BT_AUTH_TOKEN_LENGTH); 762 buffer[BT_AUTH_TOKEN_LENGTH] = 0; 763 764 // Now decrypt the request using the client's key. 765 blf_key(&ctx, clientKey, strlen(clientKey)); 766 blf_dec(&ctx, (unsigned long *) buffer, BT_AUTH_TOKEN_LENGTH / 4); 767 768// printf("\tDecrypted buffer = [%s]\n", buffer); 769 770 // The encrypted buffer may have been padded with spaces to make its length 771 // evenly divisible by four. 772 i = strlen(buffer); 773 while (buffer[--i] == ' ' && i >= 0) 774 buffer[i] = 0; 775 776 // Once decrypted, we can extract the server being contacted. 777 memcpy(share, buffer, B_FILE_NAME_LENGTH); 778 for (i = B_FILE_NAME_LENGTH - 1; i && share[i] == ' '; i--); 779 share[i + 1] = 0; 780// printf("\tShare = %s\n", share); 781 782 // The remainder of the buffer is the MD5-encoded client name. 783 memcpy(user, &buffer[B_FILE_NAME_LENGTH], MAX_USERNAME_LENGTH); 784 for (i = MAX_USERNAME_LENGTH - 1; i && user[i] == ' '; i--); 785 user[i + 1] = 0; 786 787// printf("\tComparing: Client [%s] and tok [%s]\n", client, user); 788 if (strcmp(client, user) != 0) 789 { 790 recordLogin(server, share, client, false); 791 return EACCES; 792 } 793 794 recordLogin(server, share, client, true); 795 generateTicket(client, share, clientKey, response); 796 797 return B_OK; 798} 799 800void recordLogin(char *server, char *share, char *client, bool authenticated) 801{ 802 FILE *fp; 803 struct tm *localTime; 804 time_t curTime; 805 char path[B_PATH_NAME_LENGTH], timeStamp[50]; 806 807 if (!isServerRecordingLogins(server)) 808 return; 809 810 // Obtain the filename for the log file. 811 find_directory(B_COMMON_LOG_DIRECTORY, 0, false, path, sizeof(path)); 812 strcat(path, "/BeServed-Logins.log"); 813 814 // Build the time stamp. 815 curTime = time(NULL); 816 localTime = localtime(&curTime); 817 strftime(timeStamp, sizeof(timeStamp), "%m/%d/%Y %H:%M:%S", localTime); 818 819 fp = fopen(path, "a"); 820 if (fp) 821 { 822 fprintf(fp, "%s: %s [%s] %s %s\n", timeStamp, server, 823 authenticated ? share : "--", 824 client, 825 authenticated ? "authenticated" : "rejected"); 826 fclose(fp); 827 } 828} 829 830int cmdReadUsers(DIR **dir, char *user, char *fullName) 831{ 832 struct dirent *dirInfo; 833 834 if (!user || !fullName) 835 return EINVAL; 836 837 if (!*dir) 838 *dir = OpenUsers(); 839 840 if (*dir) 841 if ((dirInfo = ReadUser(*dir)) != NULL) 842 { 843 strcpy(user, dirInfo->d_name); 844 getUserFullName(user, fullName, MAX_DESC_LENGTH); 845 return B_OK; 846 } 847 else 848 { 849 CloseUsers(*dir); 850 return ENOENT; 851 } 852 853 return EINVAL; 854} 855 856int cmdReadGroups(DIR **dir, char *group) 857{ 858 struct dirent *dirInfo; 859 860 if (!group) 861 return EINVAL; 862 863 if (!*dir) 864 *dir = OpenGroups(); 865 866 if (*dir) 867 if ((dirInfo = ReadGroup(*dir)) != NULL) 868 { 869 strcpy(group, dirInfo->d_name); 870 return B_OK; 871 } 872 else 873 { 874 CloseGroups(*dir); 875 return ENOENT; 876 } 877 878 return EINVAL; 879} 880 881int cmdWhichGroups(DIR **dir, char *user, char *group) 882{ 883 int error = cmdReadGroups(dir, group); 884 while (error == B_OK) 885 { 886 if (isUserInGroup(user, group)) 887 return B_OK; 888 889 error = cmdReadGroups(dir, group); 890 } 891 892 return error; 893} 894 895//////////////////////////////////////////////////////////////////// 896 897void netcmdAuthenticate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 898{ 899 bt_outPacket packet; 900 int client, error; 901 char response[256]; 902 903 client = session->socket; 904 905 error = cmdAuthenticate(session->client_s_addr, argv[0].data, argv[1].data, response); 906 btRPCCreateAck(&packet, xid, error); 907 if (error == B_OK) 908 btRPCPutString(&packet, response, strlen(response)); 909 910 btRPCSendAck(client, &packet); 911} 912 913void netcmdReadUsers(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 914{ 915 bt_outPacket packet; 916 int client, error; 917 DIR *dir = (DIR *)(*((int32 *) argv[0].data)); 918 char user[MAX_USERNAME_LENGTH + 1], fullName[MAX_DESC_LENGTH + 1]; 919 int entries = 0; 920 921 client = session->socket; 922 923 error = cmdReadUsers(&dir, user, fullName); 924 if (error != B_OK) 925 { 926 btRPCCreateAck(&packet, xid, error); 927 btRPCSendAck(client, &packet); 928 return; 929 } 930 931 btRPCCreateAck(&packet, xid, B_OK); 932 while (error == B_OK) 933 { 934 btRPCPutString(&packet, user, strlen(user)); 935 btRPCPutString(&packet, fullName, strlen(fullName)); 936 937 if (++entries >= 80) 938 break; 939 940 error = cmdReadUsers(&dir, user, fullName); 941 btRPCPutInt32(&packet, error); 942 } 943 944 // If we exhausted the list of directory entries without filling 945 // the buffer, add an error message that will prevent the client 946 // from requesting further entries. 947 if (entries < 80) 948 btRPCPutInt32(&packet, ENOENT); 949 950 btRPCSendAck(client, &packet); 951} 952 953void netcmdReadGroups(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 954{ 955 bt_outPacket packet; 956 int client, error; 957 DIR *dir = (DIR *)(*((int32 *) argv[0].data)); 958 char group[MAX_USERNAME_LENGTH + 1]; 959 int entries = 0; 960 961 client = session->socket; 962 963 error = cmdReadGroups(&dir, group); 964 if (error != B_OK) 965 { 966 btRPCCreateAck(&packet, xid, error); 967 btRPCSendAck(client, &packet); 968 return; 969 } 970 971 btRPCCreateAck(&packet, xid, B_OK); 972 while (error == B_OK) 973 { 974 btRPCPutString(&packet, group, strlen(group)); 975 976 if (++entries >= 80) 977 break; 978 979 error = cmdReadGroups(&dir, group); 980 btRPCPutInt32(&packet, error); 981 } 982 983 // If we exhausted the list of directory entries without filling 984 // the buffer, add an error message that will prevent the client 985 // from requesting further entries. 986 if (entries < 80) 987 btRPCPutInt32(&packet, ENOENT); 988 989 btRPCSendAck(client, &packet); 990} 991 992void netcmdWhichGroups(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 993{ 994 bt_outPacket packet; 995 int client, error; 996 DIR *dir = 0; 997 char group[MAX_USERNAME_LENGTH + 1]; 998 int entries = 0; 999 1000 client = session->socket; 1001 1002 error = cmdWhichGroups(&dir, argv[0].data, group); 1003 if (error != B_OK) 1004 { 1005 btRPCCreateAck(&packet, xid, error); 1006 btRPCSendAck(client, &packet); 1007 return; 1008 } 1009 1010 btRPCCreateAck(&packet, xid, B_OK); 1011 while (error == B_OK) 1012 { 1013 btRPCPutString(&packet, group, strlen(group)); 1014 1015 if (++entries >= 80) 1016 break; 1017 1018 error = cmdWhichGroups(&dir, argv[0].data, group); 1019 btRPCPutInt32(&packet, error); 1020 } 1021 1022 // If we exhausted the list of directory entries without filling 1023 // the buffer, add an error message that will prevent the client 1024 // from requesting further entries. 1025 if (entries < 80) 1026 btRPCPutInt32(&packet, ENOENT); 1027 1028 btRPCSendAck(client, &packet); 1029} 1030 1031// netcmdQuit() 1032// 1033void netcmdQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 1034{ 1035 bt_outPacket packet; 1036 int client; 1037 1038 client = session->socket; 1039 btRPCCreateAck(&packet, xid, B_OK); 1040 btRPCSendAck(client, &packet); 1041} 1042