| | 100 | } |
|---|
| | 101 | |
|---|
| | 102 | int SortCommandList(const void *a, const void *b) |
|---|
| | 103 | { |
|---|
| | 104 | return strcmp((*(cmd_t**)a)->name, (*(cmd_t**)b)->name); |
|---|
| | 105 | } |
|---|
| | 106 | |
|---|
| | 107 | void ListCommands() |
|---|
| | 108 | { |
|---|
| | 109 | cmd_t *cmd; |
|---|
| | 110 | array_t *cmds = array_alloc(); |
|---|
| | 111 | int length = 0, i; |
|---|
| | 112 | |
|---|
| | 113 | /* first pass, get maximum command length and number of commands we have |
|---|
| | 114 | permission to use */ |
|---|
| | 115 | for (cmd = First; cmd != NULL; cmd = cmd->next) { |
|---|
| | 116 | if (strcmp(cmd->name, "DEFAULT") && VerifyPermissions(cmd) >= 0) { |
|---|
| | 117 | int l = strlen(cmd->name); |
|---|
| | 118 | |
|---|
| | 119 | for (i = 0; i < cmds->size; ++i) |
|---|
| | 120 | if (!strcmp(((cmd_t*)cmds->data[i])->name, cmd->name)) |
|---|
| | 121 | break; |
|---|
| | 122 | if (i == cmds->size) { |
|---|
| | 123 | if (l > length) length = l; |
|---|
| | 124 | array_push(cmds, cmd); |
|---|
| | 125 | } |
|---|
| | 126 | } |
|---|
| | 127 | } |
|---|
| | 128 | |
|---|
| | 129 | qsort(cmds->data, cmds->size, sizeof(void*), SortCommandList); |
|---|
| | 130 | |
|---|
| | 131 | /* second pass, display */ |
|---|
| | 132 | for (i = 0; i < cmds->size; ++i) { |
|---|
| | 133 | cmd = cmds->data[i]; |
|---|
| | 134 | |
|---|
| | 135 | if (!strcmp(cmd->name, "DEFAULT")) continue; |
|---|
| | 136 | |
|---|
| | 137 | if (VerifyPermissions(cmd) >= 0) { |
|---|
| | 138 | char *help = FindOpt(cmd, "help"); |
|---|
| | 139 | |
|---|
| | 140 | if (!help) help = "(no help available)"; |
|---|
| | 141 | printf("%-*s", length + 2, cmd->name); |
|---|
| | 142 | while (*help) { |
|---|
| | 143 | int j; |
|---|
| | 144 | |
|---|
| | 145 | printf("%-*.*s\n", 77 - length, 77 - length, help); |
|---|
| | 146 | for (j = 0; j < 77 - length && *help; ++j, ++help) ; |
|---|
| | 147 | if (j == 77 - length) |
|---|
| | 148 | printf("%-*s", length + 2, ""); |
|---|
| | 149 | } |
|---|
| | 150 | } |
|---|
| | 151 | } |
|---|
| | 152 | array_free(cmds); |
|---|
| | 444 | int VerifyPermissions(cmd_t *cmd) |
|---|
| | 445 | { |
|---|
| | 446 | int gr_fail = 1, uid_fail = 1, netgr_fail = 1; |
|---|
| | 447 | int i; |
|---|
| | 448 | char *cp, str[MAXSTRLEN], hostname[HOST_NAME_MAX]; |
|---|
| | 449 | regexp *reg1 = NULL; |
|---|
| | 450 | struct passwd *pw; |
|---|
| | 451 | #ifdef USE_PAM |
|---|
| | 452 | struct pam_conv pamconv = { pam_conversation, NULL }; |
|---|
| | 453 | pam_handle_t *pam; |
|---|
| | 454 | #endif |
|---|
| | 455 | struct group *gr; |
|---|
| | 456 | |
|---|
| | 457 | /* root always has access - it is pointless refusing */ |
|---|
| | 458 | if (getuid() == 0) |
|---|
| | 459 | return 0; |
|---|
| | 460 | |
|---|
| | 461 | if (gethostname(hostname, HOST_NAME_MAX) == -1) |
|---|
| | 462 | return logger(LOG_ERR, "Could not get hostname"); |
|---|
| | 463 | |
|---|
| | 464 | if ((pw = getpwuid(getuid())) == NULL) |
|---|
| | 465 | return logger(LOG_ERR, "Could not get uid of current effective uid"); |
|---|
| | 466 | |
|---|
| | 467 | if ((cp = FindOpt(cmd, "groups")) != NULL) { |
|---|
| | 468 | char grouphost[MAXSTRLEN + HOST_NAME_MAX], |
|---|
| | 469 | regstr[MAXSTRLEN]; |
|---|
| | 470 | |
|---|
| | 471 | for (cp = GetField(cp, str, MAXSTRLEN - 5); cp != NULL; cp = GetField(cp, str, MAXSTRLEN - 5)) { |
|---|
| | 472 | strcpy(regstr, "^("); |
|---|
| | 473 | strcat(regstr, str); |
|---|
| | 474 | strcat(regstr, ")$"); |
|---|
| | 475 | |
|---|
| | 476 | if ((reg1 = regcomp(regstr)) == NULL) |
|---|
| | 477 | return logger(LOG_ERR, "Invalid regex '%s'", regstr); |
|---|
| | 478 | |
|---|
| | 479 | if ((gr = getgrgid(pw->pw_gid)) != NULL) { |
|---|
| | 480 | strcpy(grouphost, gr->gr_name); |
|---|
| | 481 | strcat(grouphost, "@"); |
|---|
| | 482 | strcat(grouphost, hostname); |
|---|
| | 483 | |
|---|
| | 484 | if (regexec(reg1,gr->gr_name) == 1 || regexec(reg1, grouphost)) { |
|---|
| | 485 | gr_fail = 0; |
|---|
| | 486 | break; |
|---|
| | 487 | } |
|---|
| | 488 | } |
|---|
| | 489 | |
|---|
| | 490 | setgrent(); |
|---|
| | 491 | while ((gr = getgrent()) != NULL) { |
|---|
| | 492 | i = 0; |
|---|
| | 493 | while (gr->gr_mem[i] != NULL) { |
|---|
| | 494 | if (strcmp(gr->gr_mem[i], pw->pw_name)==0) break; |
|---|
| | 495 | i++; |
|---|
| | 496 | } |
|---|
| | 497 | |
|---|
| | 498 | if (gr->gr_mem[i] != NULL) { |
|---|
| | 499 | strcpy(grouphost, gr->gr_name); |
|---|
| | 500 | strcat(grouphost, "@"); |
|---|
| | 501 | strcat(grouphost, hostname); |
|---|
| | 502 | if (regexec(reg1, gr->gr_name) == 1 || regexec(reg1, grouphost)) { |
|---|
| | 503 | gr_fail = 0; |
|---|
| | 504 | break; |
|---|
| | 505 | } |
|---|
| | 506 | } |
|---|
| | 507 | } |
|---|
| | 508 | } |
|---|
| | 509 | } |
|---|
| | 510 | if(reg1 != NULL){ |
|---|
| | 511 | free(reg1); |
|---|
| | 512 | reg1=NULL; |
|---|
| | 513 | } |
|---|
| | 514 | |
|---|
| | 515 | if (gr_fail && ((cp = FindOpt(cmd, "users")) != NULL)) { |
|---|
| | 516 | char currenttime[13], userhost[MAXSTRLEN + HOST_NAME_MAX], |
|---|
| | 517 | regstr[MAXSTRLEN]; |
|---|
| | 518 | time_t now = time(NULL); |
|---|
| | 519 | |
|---|
| | 520 | strftime(currenttime, 13, "%Y%m%d%H%M", localtime(&now)); |
|---|
| | 521 | |
|---|
| | 522 | for (cp=GetField(cp, str, MAXSTRLEN - 5); cp!=NULL; cp=GetField(cp, str, MAXSTRLEN - 5)) { |
|---|
| | 523 | char expiretime[13], *expirestart = strchr(str, '/'); |
|---|
| | 524 | |
|---|
| | 525 | if (expirestart) *expirestart = 0; |
|---|
| | 526 | |
|---|
| | 527 | strcpy(regstr, "^("); |
|---|
| | 528 | strcat(regstr, str); |
|---|
| | 529 | strcat(regstr, ")$"); |
|---|
| | 530 | |
|---|
| | 531 | strcpy(userhost, pw->pw_name); |
|---|
| | 532 | strcat(userhost, "@"); |
|---|
| | 533 | strcat(userhost, hostname); |
|---|
| | 534 | |
|---|
| | 535 | if ((reg1=regcomp(regstr)) == NULL) |
|---|
| | 536 | return logger(LOG_ERR, "Invalid regex '%s'", regstr); |
|---|
| | 537 | |
|---|
| | 538 | if (regexec(reg1,pw->pw_name) == 1 || regexec(reg1, userhost) == 1) { |
|---|
| | 539 | /* valid user, check expiry (if any) */ |
|---|
| | 540 | if (expirestart) { |
|---|
| | 541 | int i; |
|---|
| | 542 | |
|---|
| | 543 | ++expirestart; |
|---|
| | 544 | |
|---|
| | 545 | /* ensure at least some sanity in the expiry time */ |
|---|
| | 546 | for (i = 0; expirestart[i]; ++i) { |
|---|
| | 547 | if (i > 11) |
|---|
| | 548 | return logger(LOG_ERR, "Expiry value (%s) has too many digits", expirestart); |
|---|
| | 549 | if (!isdigit(expirestart[i])) |
|---|
| | 550 | return logger(LOG_ERR, "Expiry value (%s) has non-numeric characters", expirestart); |
|---|
| | 551 | } |
|---|
| | 552 | |
|---|
| | 553 | strcpy(expiretime, "000000000000"); /* YYYYMMDD[HHmm] */ |
|---|
| | 554 | strncpy(expiretime, expirestart, strlen(expirestart)); |
|---|
| | 555 | |
|---|
| | 556 | if (strcmp(currenttime, expiretime) >= 0) |
|---|
| | 557 | return logger(LOG_ERR, "Access expired at %s", expiretime); |
|---|
| | 558 | } |
|---|
| | 559 | |
|---|
| | 560 | uid_fail = 0; |
|---|
| | 561 | break; |
|---|
| | 562 | } |
|---|
| | 563 | } |
|---|
| | 564 | } |
|---|
| | 565 | if(reg1 != NULL){ |
|---|
| | 566 | free(reg1); |
|---|
| | 567 | reg1=NULL; |
|---|
| | 568 | } |
|---|
| | 569 | |
|---|
| | 570 | if (uid_fail && (cp = FindOpt(cmd, "netgroups")) != NULL) { |
|---|
| | 571 | for (cp = GetField(cp, str, MAXSTRLEN - 5); cp != NULL && netgr_fail; cp = GetField(cp, str, MAXSTRLEN - 5)) { |
|---|
| | 572 | if (innetgr(str, hostname, pw->pw_name, NULL)) { |
|---|
| | 573 | netgr_fail = 0; |
|---|
| | 574 | break; |
|---|
| | 575 | } |
|---|
| | 576 | } |
|---|
| | 577 | } |
|---|
| | 578 | |
|---|
| | 579 | if (gr_fail && uid_fail && netgr_fail) |
|---|
| | 580 | return -1; |
|---|
| | 581 | return 0; |
|---|
| | 582 | } |
|---|
| | 583 | |
|---|
| 473 | | if (gethostname(hostname, HOST_NAME_MAX) == -1) |
|---|
| 474 | | return logger(LOG_ERR, "Could not get hostname"); |
|---|
| 475 | | |
|---|
| 476 | | if ((pw = getpwuid(getuid())) == NULL) |
|---|
| 477 | | return logger(LOG_ERR, "Could not get uid of current effective uid"); |
|---|
| 478 | | |
|---|
| 479 | | if ((cp = FindOpt(cmd, "groups")) != NULL) { |
|---|
| 480 | | char grouphost[MAXSTRLEN + HOST_NAME_MAX], |
|---|
| 481 | | regstr[MAXSTRLEN]; |
|---|
| 482 | | |
|---|
| 483 | | for (cp = GetField(cp, str, MAXSTRLEN - 5); cp != NULL; cp = GetField(cp, str, MAXSTRLEN - 5)) { |
|---|
| 484 | | strcpy(regstr, "^("); |
|---|
| 485 | | strcat(regstr, str); |
|---|
| 486 | | strcat(regstr, ")$"); |
|---|
| 487 | | |
|---|
| 488 | | if ((reg1 = regcomp(regstr)) == NULL) |
|---|
| 489 | | return logger(LOG_ERR, "Invalid regex '%s'", regstr); |
|---|
| 490 | | |
|---|
| 491 | | if ((gr = getgrgid(pw->pw_gid)) != NULL) { |
|---|
| 492 | | strcpy(grouphost, gr->gr_name); |
|---|
| 493 | | strcat(grouphost, "@"); |
|---|
| 494 | | strcat(grouphost, hostname); |
|---|
| 495 | | |
|---|
| 496 | | if (regexec(reg1,gr->gr_name) == 1 || regexec(reg1, grouphost)) { |
|---|
| 497 | | gr_fail = 0; |
|---|
| 498 | | break; |
|---|
| 499 | | } |
|---|
| 500 | | } |
|---|
| 501 | | |
|---|
| 502 | | setgrent(); |
|---|
| 503 | | while ((gr = getgrent()) != NULL) { |
|---|
| 504 | | i = 0; |
|---|
| 505 | | while (gr->gr_mem[i] != NULL) { |
|---|
| 506 | | if (strcmp(gr->gr_mem[i], pw->pw_name)==0) break; |
|---|
| 507 | | i++; |
|---|
| 508 | | } |
|---|
| 509 | | |
|---|
| 510 | | if (gr->gr_mem[i] != NULL) { |
|---|
| 511 | | strcpy(grouphost, gr->gr_name); |
|---|
| 512 | | strcat(grouphost, "@"); |
|---|
| 513 | | strcat(grouphost, hostname); |
|---|
| 514 | | if (regexec(reg1, gr->gr_name) == 1 || regexec(reg1, grouphost)) { |
|---|
| 515 | | gr_fail = 0; |
|---|
| 516 | | break; |
|---|
| 517 | | } |
|---|
| 518 | | } |
|---|
| 519 | | } |
|---|
| 520 | | } |
|---|
| 521 | | } |
|---|
| 522 | | if(reg1 != NULL){ |
|---|
| 523 | | free(reg1); |
|---|
| 524 | | reg1=NULL; |
|---|
| 525 | | } |
|---|
| 526 | | |
|---|
| 527 | | if (gr_fail && ((cp = FindOpt(cmd, "users")) != NULL)) { |
|---|
| 528 | | char currenttime[13], userhost[MAXSTRLEN + HOST_NAME_MAX], |
|---|
| 529 | | regstr[MAXSTRLEN]; |
|---|
| 530 | | time_t now = time(NULL); |
|---|
| 531 | | |
|---|
| 532 | | strftime(currenttime, 13, "%Y%m%d%H%M", localtime(&now)); |
|---|
| 533 | | |
|---|
| 534 | | for (cp=GetField(cp, str, MAXSTRLEN - 5); cp!=NULL; cp=GetField(cp, str, MAXSTRLEN - 5)) { |
|---|
| 535 | | char expiretime[13], *expirestart = strchr(str, '/'); |
|---|
| 536 | | |
|---|
| 537 | | if (expirestart) *expirestart = 0; |
|---|
| 538 | | |
|---|
| 539 | | strcpy(regstr, "^("); |
|---|
| 540 | | strcat(regstr, str); |
|---|
| 541 | | strcat(regstr, ")$"); |
|---|
| 542 | | |
|---|
| 543 | | strcpy(userhost, pw->pw_name); |
|---|
| 544 | | strcat(userhost, "@"); |
|---|
| 545 | | strcat(userhost, hostname); |
|---|
| 546 | | |
|---|
| 547 | | if ((reg1=regcomp(regstr)) == NULL) |
|---|
| 548 | | return logger(LOG_ERR, "Invalid regex '%s'", regstr); |
|---|
| 549 | | |
|---|
| 550 | | if (regexec(reg1,pw->pw_name) == 1 || regexec(reg1, userhost) == 1) { |
|---|
| 551 | | /* valid user, check expiry (if any) */ |
|---|
| 552 | | if (expirestart) { |
|---|
| 553 | | int i; |
|---|
| 554 | | |
|---|
| 555 | | ++expirestart; |
|---|
| 556 | | |
|---|
| 557 | | /* ensure at least some sanity in the expiry time */ |
|---|
| 558 | | for (i = 0; expirestart[i]; ++i) { |
|---|
| 559 | | if (i > 11) |
|---|
| 560 | | return logger(LOG_ERR, "Expiry value (%s) has too many digits", expirestart); |
|---|
| 561 | | if (!isdigit(expirestart[i])) |
|---|
| 562 | | return logger(LOG_ERR, "Expiry value (%s) has non-numeric characters", expirestart); |
|---|
| 563 | | } |
|---|
| 564 | | |
|---|
| 565 | | strcpy(expiretime, "000000000000"); /* YYYYMMDD[HHmm] */ |
|---|
| 566 | | strncpy(expiretime, expirestart, strlen(expirestart)); |
|---|
| 567 | | |
|---|
| 568 | | if (strcmp(currenttime, expiretime) >= 0) |
|---|
| 569 | | return logger(LOG_ERR, "Access expired at %s", expiretime); |
|---|
| 570 | | } |
|---|
| 571 | | |
|---|
| 572 | | uid_fail = 0; |
|---|
| 573 | | break; |
|---|
| 574 | | } |
|---|
| 575 | | } |
|---|
| 576 | | } |
|---|
| 577 | | if(reg1 != NULL){ |
|---|
| 578 | | free(reg1); |
|---|
| 579 | | reg1=NULL; |
|---|
| 580 | | } |
|---|
| 581 | | |
|---|
| 582 | | if (uid_fail && (cp = FindOpt(cmd, "netgroups")) != NULL) { |
|---|
| 583 | | for (cp = GetField(cp, str, MAXSTRLEN - 5); cp != NULL && netgr_fail; cp = GetField(cp, str, MAXSTRLEN - 5)) { |
|---|
| 584 | | if (innetgr(str, hostname, pw->pw_name, NULL)) { |
|---|
| 585 | | netgr_fail = 0; |
|---|
| 586 | | break; |
|---|
| 587 | | } |
|---|
| 588 | | } |
|---|
| 589 | | } |
|---|
| 590 | | |
|---|
| 591 | | if (gr_fail && uid_fail && netgr_fail) |
|---|
| | 669 | if ((i = VerifyPermissions(cmd) < 0)) |
|---|