int create_socket_connect_verify(uint16_t server_port, uint16_t max_clients, char* module_name, int setupdone, int *connection_id) { int connectSocket; mysyslog(LOG_INFO, "Waiting connections on %d..\n", server_port); if((connectSocket = create_socket_and_listen(server_port, setupdone)) < 0) { mysyslog(LOG_ERR, "Cannot create socket to listen.\n"); return ERROR; } if(verify_max_clients(max_clients, connectSocket, module_name) != OK) { mysyslog(LOG_ERR, "verify_max_clients returned not OK.\n"); return ERROR; } if((*connection_id = get_new_port(connectSocket, used_ports)) == NO_FREE_CONN) { mysyslog(LOG_ERR, "get_new_port returned NO_FREE_CONN\n"); return ERROR; } return connectSocket; }
int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { const char *PAM_user = NULL; int ret; if (!cgm_dbus_connect()) { mysyslog(LOG_ERR, "Failed to connect to cgmanager\n"); return PAM_SESSION_ERR; } if (argc > 1 && strcmp(argv[0], "-c") == 0) ctrl_list = validate_and_dup(argv[1]); if (!ctrl_list) get_active_controllers(); cgm_escape(); ret = pam_get_user(pamh, &PAM_user, NULL); if (ret != PAM_SUCCESS) { cgm_dbus_disconnect(); mysyslog(LOG_ERR, "PAM-CGM: couldn't get user\n"); return PAM_SESSION_ERR; } ret = handle_login(PAM_user); cgm_dbus_disconnect(); return ret; }
int release_dead_connection_entry(int child_pid, struct used_port *ports) { int i; if(child_pid <= 0) { mysyslog(LOG_INFO, "child_pid cannot be less or equal zero in module %s. Please investigate this issue.\n", ext_module_name); return -1; } if(ports == NULL) { mysyslog(LOG_INFO, "Used_port struct null in module %s. Please investigate this issue.\n", ext_module_name); return -1; } for(i=0; i<ext_max_clients; i++) { if(ports[i].childpid == child_pid) { ports[i].childpid = 0; ports[i].ports = 0; total_clients--; mysyslog(LOG_INFO, "Released %s connection number %d\n", ext_module_name, i); return 0; } } return -1; }
/** \brief create_socket_and_listen(int server_port, struct sockaddr_in * clientAddress, int *mysocket ) function is used to create and wait for connections of stations wishing to communicate with this controller. * * \param server_port int used to indicate to wich port it should listen for connections. * \param clientAddress struct sockaddr_in* structure needed to create the listen socket. * \param mysocket int* variable to return the listening socket because it's used in other functions. * \return int returns a connectSocket when a stations connects to it. * */ int create_socket_and_listen(int server_port, int setupdone ) { int connectSocket, err; static int mysocket; static struct sockaddr_in serverAddress; static socklen_t clientAddressLength; struct sockaddr_in clientAddress; int yes; if(setupdone == 0) /* do it only the first time. */ { mysocket = socket(AF_INET, SOCK_STREAM, 0); if (mysocket < 0) return -1; serverAddress.sin_family = AF_INET; serverAddress.sin_addr.s_addr = htonl(INADDR_ANY); serverAddress.sin_port = htons(server_port); yes=1; if (setsockopt(mysocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); return -1; } if ((err = bind(mysocket,(struct sockaddr *) &serverAddress,sizeof(serverAddress))) < 0) { mysyslog(LOG_ERR, "cannot bind socket %s\n", strerror(-err)); return -1; } if ( listen(mysocket, 10) != 0 ) { perror("Can't configure listening port"); return -1; } mysyslog(LOG_INFO, "Socket created!\nWaiting for a TCP connection\n"); clientAddressLength = sizeof(clientAddress); } connectSocket = accept(mysocket, (struct sockaddr *) &clientAddress, &clientAddressLength); /* accept connection as usual */ mysyslog("Connection: %s:%d\n",inet_ntoa(clientAddress.sin_addr), ntohs(clientAddress.sin_port)); if (connectSocket < 0) { mysyslog(LOG_ERR, "cannot accept connection \n"); return -1; } mysyslog(LOG_INFO, "Connection accepted\n"); return connectSocket; }
/* * Log a message to syslog, pre-pending the username and splitting the * message into parts if it is longer than syslog_maxlen. */ static void do_syslog(int pri, char *msg) { size_t len, maxlen; char *p, *tmp, save; const char *fmt; int oldlocale; debug_decl(do_syslog, SUDOERS_DEBUG_LOGGING) /* A priority of -1 corresponds to "none". */ if (pri == -1) debug_return; sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale); /* * Log the full line, breaking into multiple syslog(3) calls if necessary */ fmt = _("%8s : %s"); maxlen = def_syslog_maxlen - (strlen(fmt) - 5 + strlen(user_name)); for (p = msg; *p != '\0'; ) { len = strlen(p); if (len > maxlen) { /* * Break up the line into what will fit on one syslog(3) line * Try to avoid breaking words into several lines if possible. */ tmp = memrchr(p, ' ', maxlen); if (tmp == NULL) tmp = p + maxlen; /* NULL terminate line, but save the char to restore later */ save = *tmp; *tmp = '\0'; mysyslog(pri, fmt, user_name, p); *tmp = save; /* restore saved character */ /* Advance p and eliminate leading whitespace */ for (p = tmp; *p == ' '; p++) continue; } else { mysyslog(pri, fmt, user_name, p); p += len; } fmt = _("%8s : (command continued) %s"); maxlen = def_syslog_maxlen - (strlen(fmt) - 5 + strlen(user_name)); } sudoers_setlocale(oldlocale, NULL); debug_return; }
/** \brief child_terminated() function is connected via a signal to the termination of a child process. * The function releases the connection in the master connection's table kept by the parent. * \param None * \return None * */ void child_terminated(void) { pid_t child_pid; int status; child_pid = wait(&status); mysyslog(LOG_INFO, "Child exited with PID=%d\n", child_pid); if(release_dead_connection_entry(child_pid, used_ports) != 0) mysyslog(LOG_INFO, "Tried to release connection in module %s with child_pid %d but was not found on the table\n", ext_module_name, child_pid); return; }
/* * Log a message to syslog, pre-pending the username and splitting the * message into parts if it is longer than MAXSYSLOGLEN. */ static void do_syslog(int pri, char *msg) { size_t len, maxlen; char *p, *tmp, save; const char *fmt; #ifdef HAVE_SETLOCALE const char *old_locale = estrdup(setlocale(LC_ALL, NULL)); if (!setlocale(LC_ALL, def_sudoers_locale)) setlocale(LC_ALL, "C"); #endif /* HAVE_SETLOCALE */ /* * Log the full line, breaking into multiple syslog(3) calls if necessary */ fmt = _(FMT_FIRST); maxlen = MAXSYSLOGLEN - (strlen(fmt) - 5 + strlen(user_name)); for (p = msg; *p != '\0'; ) { len = strlen(p); if (len > maxlen) { /* * Break up the line into what will fit on one syslog(3) line * Try to avoid breaking words into several lines if possible. */ tmp = memrchr(p, ' ', maxlen); if (tmp == NULL) tmp = p + maxlen; /* NULL terminate line, but save the char to restore later */ save = *tmp; *tmp = '\0'; mysyslog(pri, fmt, user_name, p); *tmp = save; /* restore saved character */ /* Advance p and eliminate leading whitespace */ for (p = tmp; *p == ' '; p++) ; } else { mysyslog(pri, fmt, user_name, p); p += len; } fmt = _(FMT_CONTD); maxlen = MAXSYSLOGLEN - (strlen(fmt) - 5 + strlen(user_name)); } #ifdef HAVE_SETLOCALE setlocale(LC_ALL, old_locale); efree((void *)old_locale); #endif /* HAVE_SETLOCALE */ }
int closeconnection(int connectSocket, SSL* ssl, SSL_CTX* ctx, char *module_name) { if (module_name == NULL) { mysyslog(LOG_ERR, "Argunments to closeconnection are null\n"); } else mysyslog(LOG_INFO, "Quiting %s ethernet command parser\n", module_name); shutdown(connectSocket,SHUT_RDWR); close(connectSocket); SSL_free(ssl); /* release SSL state */ SSL_CTX_free(ctx); /* release SSL context */ return 0; }
static void bye (int signum) { #ifdef TCSETS (void) ioctl (0, TCSETS, &termorig); #endif if (seteuid(orig_euid) != 0) { perror ("Reacquiring uid 0 failed"); bye (EXIT_FAILURE); } set_perms_and_close_file(&timing); set_perms_and_close_file(&script); #ifdef RECORDINPUT set_perms_and_close_file(&input); #endif if (setuid(getuid()) != 0) { perror ("Dropping setuid 0 failed"); bye (EXIT_FAILURE); } if (sudosh_option.priority != -1) mysyslog (sudosh_option.priority, "stopping session for %s as %s, tty %s, shell %s", user.from, user.to, ttyname (0), user.shell.ptr); exit (signum); }
int get_priority(const u_char *new_priority) { int pri = PRIORITY; if (!strncasecmp(new_priority, "log_", 4)) new_priority += 4; if (!strcasecmp(new_priority, "alert")) pri = LOG_ALERT; else if (!strcasecmp(new_priority, "crit")) pri = LOG_CRIT; else if (!strcasecmp(new_priority, "debug")) pri = LOG_DEBUG; else if (!strcasecmp(new_priority, "emerg")) pri = LOG_EMERG; else if (!strcasecmp(new_priority, "err")) pri = LOG_ERR; else if (!strcasecmp(new_priority, "error")) pri = LOG_ERR; else if (!strcasecmp(new_priority, "info")) pri = LOG_INFO; else if (!strcasecmp(new_priority, "notice")) pri = LOG_NOTICE; else if (!strcasecmp(new_priority, "panic")) pri = LOG_EMERG; else if (!strcasecmp(new_priority, "warn")) pri = LOG_WARNING; else if (!strcasecmp(new_priority, "warning")) pri = LOG_WARNING; else mysyslog("Invalid priority: \"%s\" - falling back to default.", new_priority); return (pri); }
int statcom_main(uint16_t server_port, uint16_t max_clients, char* module_name, int (*call_command_handler_function) (SSL *, int)) { int setupdone=0, connection_id, connectSocket; pid_t pid; /*SSL specific.*/ SSL *ssl; SSL_CTX *ctx; total_clients = 0; ctx = initialize_SSL(server_port, max_clients, module_name); while(1) /*while loop to serve many connections. When one connection arrives, a new process is forked to handle it.*/ { /*and the parent process comes here again to continue listening.*/ if((connectSocket = create_socket_connect_verify(server_port, max_clients, module_name, setupdone, &connection_id)) == ERROR) goto error; switch(pid = fork()) /* here a new child process is created and the parent continues.*/ { case -1:/*something went wrong..*/ mysyslog(LOG_ERR, "Error in forking a new %s connection.\nAborting.....\n", module_name); break; case 0:/*child process*/ signal(SIGCHLD,SIG_IGN); /* to keep track of when a child is terminated.*/ signal(SIGCLD,SIG_IGN); /* to keep track of when a child is terminated.*/ if((ssl = do_ssl_handshake(ctx, connectSocket)) != NULL) /* if OK call function to handle engstation comms.*/ call_command_handler_function(ssl, connection_id); /* this function don't return until the station ends the connection.*/ closeconnection(connectSocket, ssl, ctx, module_name); /* we're done handling this connection, the client will exit now.*/ exit(0); /*when finished handling comms, we kill the child.*/ break; default: /*parent process go on. The parent goes back to the begining of the while loop to continue listening.*/ /*the child handles the new connection.*/ setupdone = 1; mysyslog(LOG_INFO, "Parent saving PID=%d of child in slot=%d\n", pid,connection_id ); used_ports[connection_id].childpid = pid; /*save the PID of the child in the used_port table.*/ break; } error: ; /*an empty statmenent is needed by the compiler.*/ } return 0; /*we should never reach here !*/ }
int get_facility(const u_char *new_facility) { int fac = FACILITY; if (!strncasecmp(new_facility, "log_", 4)) new_facility += 4; if (!strcasecmp(new_facility, "auth")) fac = LOG_AUTH; #ifdef LOG_AUTHPRIV else if (!strcasecmp(new_facility, "authpriv")) fac = LOG_AUTHPRIV; #endif else if (!strcasecmp(new_facility, "cron")) fac = LOG_CRON; else if (!strcasecmp(new_facility, "daemon")) fac = LOG_DAEMON; #ifdef LOG_FTP else if (!strcasecmp(new_facility, "ftp")) fac = LOG_FTP; #endif else if (!strcasecmp(new_facility, "kern")) fac = LOG_KERN; else if (!strcasecmp(new_facility, "lpr")) fac = LOG_LPR; else if (!strcasecmp(new_facility, "mail")) fac = LOG_MAIL; else if (!strcasecmp(new_facility, "news")) fac = LOG_NEWS; else if (!strcasecmp(new_facility, "security")) fac = LOG_AUTH; else if (!strcasecmp(new_facility, "syslog")) fac = LOG_SYSLOG; else if (!strcasecmp(new_facility, "user")) fac = LOG_USER; else if (!strcasecmp(new_facility, "uucp")) fac = LOG_UUCP; else if (!strcasecmp(new_facility, "local0")) fac = LOG_LOCAL0; else if (!strcasecmp(new_facility, "local1")) fac = LOG_LOCAL1; else if (!strcasecmp(new_facility, "local2")) fac = LOG_LOCAL2; else if (!strcasecmp(new_facility, "local3")) fac = LOG_LOCAL3; else if (!strcasecmp(new_facility, "local4")) fac = LOG_LOCAL4; else if (!strcasecmp(new_facility, "local5")) fac = LOG_LOCAL5; else if (!strcasecmp(new_facility, "local6")) fac = LOG_LOCAL6; else if (!strcasecmp(new_facility, "local7")) fac = LOG_LOCAL7; else mysyslog("Invalid facility: \"%s\" - falling back to default.", new_facility); return (fac); }
SSL_CTX* initialize_SSL(uint16_t server_port, uint16_t max_clients, char* module_name) { SSL_CTX *ctx; mysyslog(LOG_INFO, "%s initing..\n", module_name); ext_server_port = server_port; ext_max_clients = max_clients; strcpy(ext_module_name, module_name); memset(used_ports,0,max_clients*sizeof(struct used_port)); if((ctx = InitServerCTX()) == NULL) /* initialize SSL */ { mysyslog(LOG_ERR,"Error while creating ctx\n"); abort(); } return ctx; }
void ShowCerts(SSL* ssl) { X509 *cert; char *line; cert = SSL_get_peer_certificate(ssl); if ( cert != NULL ) { printf("Client certificates:\n"); line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); mysyslog(LOG_INFO, "Subject: %s\n",line); free(line); line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); mysyslog(LOG_INFO, "Issuer: %s\n",line); free(line); X509_free(cert); } else printf("No certificates.\n"); }
static char *validate_and_dup(const char *arg) { nih_local char *d = NIH_MUST( nih_strdup(NULL, arg) ); nih_local char **valid_list = cgm_list_controllers(); char *tok; if (!valid_list) { mysyslog(LOG_ERR, "Failed to get controller list\n"); return NULL; } for (tok = strtok(d, ","); tok; tok = strtok(NULL, ",")) { if (!is_in_list(tok, valid_list)) { mysyslog(LOG_ERR, "Invalid controller: %s\n", tok); return NULL; } } return NIH_MUST( nih_strdup(NULL, arg) ); }
void makerealtime(char *task_name) { int err=0; mlockall(MCL_CURRENT|MCL_FUTURE); /* Used by Xenomai to avoid paging used RAM.*/ err = rt_task_shadow(&rt_task, task_name, ENGST_PRIORITY, ENGST_CREATE_MODE); mysyslog(LOG_INFO, "In makerealtime after shadow err = %d\n", err); /*5 secs ? if fdsched is not running, this blocks forever, why ?*/ err = rt_task_bind(&sched_task,"SCHED_PROXY",5000000000ULL); if (err < 0 ) { mysyslog(LOG_ERR, "Bind error %d in %s: %s\n",-err,ext_module_name,strerror(-err)); exit(1); } else mysyslog(LOG_INFO, "Binding engstation to sched task succesfully.\n"); return; }
int verify_max_clients(int max_clients, int connectSocket, char* module_name) { if(total_clients >= max_clients) { mysyslog(LOG_WARNING, "The number of %s connected exceeds the limit.\n", module_name); /*send "no more connections" message msg = NO_FREE_CONN; send_ushortdata(connectSocket, &msg ); TODO: perhaps this could be sent only with plain sockets, because no SSL yet.*/ shutdown(connectSocket,2); close(connectSocket); return NOTOK; } else return OK; }
static void get_active_controllers(void) { int i; nih_local char **list = cgm_list_controllers(); if (!list) { mysyslog(LOG_NOTICE, "unable to detect controllers"); ctrl_list = NIH_MUST( nih_strdup(NULL, "all") ); return; } for (i = 0; list[i]; i++) { if (strcmp(list[i], "name=systemd") == 0) continue; NIH_MUST( nih_strcat_sprintf(&ctrl_list, NULL, "%s%s", ctrl_list ? "," : "", list[i]) ); } }
/*There is an array that holds a map of the ports used to connect to other clients via ethernet. This function searches in the array looking for a free socket and return an index that added to the base give us the port number.*/ uint16_t get_new_port(int connectSocket, struct used_port *ports) { uint16_t port=0; while(ports[port].ports != 0) { if(port < ext_max_clients) port++; else { mysyslog(LOG_ERR, "No more free ports for %s.\n", ext_module_name); shutdown(connectSocket,SHUT_RDWR); close(connectSocket); return NO_FREE_CONN; } } ports[port].ports = 1; /* mark it as used.*/ total_clients++; /*one more client being served.*/ return port; }
/* * logger -- read and log utility * * Reads from an input and arranges to write the result on the system * log. */ int main(int argc, char **argv) { int ch, logflags, pri; char *tag, buf[1024]; char *usock = NULL; char *udpserver = NULL; char *udpport = NULL; int LogSock = -1; static const struct option longopts[] = { { "id", no_argument, 0, 'i' }, { "stderr", no_argument, 0, 's' }, { "file", required_argument, 0, 'f' }, { "priority", required_argument, 0, 'p' }, { "tag", required_argument, 0, 't' }, { "socket", required_argument, 0, 'u' }, { "udp", no_argument, 0, 'd' }, { "server", required_argument, 0, 'n' }, { "port", required_argument, 0, 'P' }, { "version", no_argument, 0, 'V' }, { "help", no_argument, 0, 'h' }, { NULL, 0, 0, 0 } }; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); atexit(close_stdout); tag = NULL; pri = LOG_NOTICE; logflags = 0; while ((ch = getopt_long(argc, argv, "f:ip:st:u:dn:P:Vh", longopts, NULL)) != -1) { switch((char)ch) { case 'f': /* file to log */ if (freopen(optarg, "r", stdin) == NULL) err(EXIT_FAILURE, _("file %s"), optarg); break; case 'i': /* log process id also */ logflags |= LOG_PID; break; case 'p': /* priority */ pri = pencode(optarg); break; case 's': /* log to standard error */ logflags |= LOG_PERROR; break; case 't': /* tag */ tag = optarg; break; case 'u': /* unix socket */ usock = optarg; break; case 'd': optd = 1; /* use datagrams */ break; case 'n': /* udp socket */ optd = 1; /* use datagrams because udp */ udpserver = optarg; break; case 'P': /* change udp port */ udpport = optarg; break; case 'V': printf(_("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING); exit(EXIT_SUCCESS); case 'h': usage(stdout); case '?': default: usage(stderr); } } argc -= optind; argv += optind; /* setup for logging */ if (!usock && !udpserver) openlog(tag ? tag : getlogin(), logflags, 0); else if (udpserver) LogSock = udpopenlog(udpserver,udpport); else LogSock = myopenlog(usock); /* log input line if appropriate */ if (argc > 0) { register char *p, *endp; size_t len; for (p = buf, endp = buf + sizeof(buf) - 2; *argv;) { len = strlen(*argv); if (p + len > endp && p > buf) { if (!usock && !udpserver) syslog(pri, "%s", buf); else mysyslog(LogSock, logflags, pri, tag, buf); p = buf; } if (len > sizeof(buf) - 1) { if (!usock && !udpserver) syslog(pri, "%s", *argv++); else mysyslog(LogSock, logflags, pri, tag, *argv++); } else { if (p != buf) *p++ = ' '; memmove(p, *argv++, len); *(p += len) = '\0'; } } if (p != buf) { if (!usock && !udpserver) syslog(pri, "%s", buf); else mysyslog(LogSock, logflags, pri, tag, buf); } } else { while (fgets(buf, sizeof(buf), stdin) != NULL) { /* glibc is buggy and adds an additional newline, so we have to remove it here until glibc is fixed */ int len = strlen(buf); if (len > 0 && buf[len - 1] == '\n') buf[len - 1] = '\0'; if (!usock && !udpserver) syslog(pri, "%s", buf); else mysyslog(LogSock, logflags, pri, tag, buf); } } if (!usock && !udpserver) closelog(); else close(LogSock); return EXIT_SUCCESS; }
int main (int argc, char *argv[], char *environ[]) { int n = 1; int valid = -1; char iobuf[BUFSIZ]; char sysconfdir[BUFSIZ]; char c_str[BUFSIZ]; char c_command[BUFSIZ]; char *p = NULL; char *rand = rand2str (16); time_t now = time ((time_t *) NULL); struct stat s; struct sigaction saterm; struct sigaction sawinch; struct sigaction sachild; struct timeval tv; double oldtime, newtime; struct stat ttybuf; int c; char argtest[BUFSIZ]; user.vshell = NULL; user.shell.ptr = NULL; user.home.ptr = NULL; user.term.ptr = NULL; progname = argv[0]; if ((p = (char *) strrchr (progname, '/')) != NULL) progname = p + 1; if (*progname == '-') loginshell = 1; /* Who are you? */ user.pw = getpwuid ((uid_t) getuid ()); if (user.pw == NULL) { fprintf (stderr, "I do not know who you are. Stopping.\n"); perror ("getpwuid"); exit (EXIT_FAILURE); } strncpy (user.to, user.pw->pw_name, BUFSIZ - 1); user.term.ptr = getenv ("TERM"); if (user.term.ptr == NULL) user.term.ptr = "dumb"; if (strlen (user.term.ptr) < 1) user.term.ptr = "dumb"; snprintf (sysconfdir, BUFSIZ - 1, "%s/sudosh.conf", SYSCONFDIR); parse (&sudosh_option, sysconfdir); while ((c = getopt (argc, argv, "c:hivV")) != EOF) { switch (c) { case 'c': // fprintf(stderr,"optarg is [%s]\n",optarg); strncpy (user.from, user.pw->pw_name, BUFSIZ - 1); strncpy (c_str, optarg, BUFSIZ - 1); strncpy (c_command, optarg, BUFSIZ - 1); p = strchr (c_str, ' '); if (p) { p[0] = 0; // fprintf(stderr,"args=%s\n",c_args); } if (c_str[0] != 0) { // Test for methods of escape if (strchr (c_command, ';') != NULL || strchr (c_command, '&') != NULL || strchr (c_command, '|') != NULL || strchr (c_command, '<') != NULL || strchr (c_command, '>') != NULL || strchr (c_command, '`') != NULL) { fprintf (stderr, "\"%s\" isn't allowed to be executed with process or redirect controls.\n", c_command); exit (EXIT_FAILURE); } // fprintf(stderr,"Testing c\n"); // Make sure that c_str is in argallow sprintf (argtest, "$%.100s$", c_str); // fprintf(stderr,"Testing for %s\n",argtest); if (strstr (sudosh_option.argallow, argtest) != NULL || strchr(sudosh_option.argallow, '*')!=NULL) { FILE *f; snprintf (script.name, (size_t) BUFSIZ - 1, "%s/%s%c%s%cinteractive%c%i%c%s", sudosh_option.logdir, user.from, sudosh_option.fdl, user.to, sudosh_option.fdl, sudosh_option.fdl, (int) now, sudosh_option.fdl, rand); f = fopen (script.name, "w"); if (f == (FILE *) 0) { fprintf (stderr, "%.100s: %.100s (%i)\n", script.name, strerror (errno), errno); exit (EXIT_FAILURE); } fprintf (f, "%.256s\n", c_str); fclose (f); execl ("/bin/sh", "sh", "-c", c_command, (char *) 0); exit (EXIT_SUCCESS); break; } else { fprintf (stderr, "\"%s\" isn't allowed to be executed.\n", c_str); exit (EXIT_FAILURE); break; } } break; case 'h': case '?': fprintf (stdout, "Usage: sudosh\n" "sudo shell that supports input and output logging to syslog\n" "\n" "-h, --help display this help and exit\n" "-i, --init initialize logdir (mkdir and chmod) (ignored for compatibility)\n" "-v, --version output version information and exit\n" "\n" "Report bugs to <%s>\n", PACKAGE_BUGREPORT); exit (EXIT_SUCCESS); break; case 'i': fprintf (stdout, "Ignoring initialize option, this is done automatically\n"); exit (EXIT_SUCCESS); break; case 'v': case 'V': fprintf (stdout, "%s version %s\n", PACKAGE_NAME, VERSION); exit (EXIT_SUCCESS); break; default: fputs ("Try `sudosh -h' for more information.\n", stderr); exit (EXIT_FAILURE); break; } } if (ttyname (0) != NULL) { if (stat (ttyname (0), &ttybuf) == 0) { if ((getpwuid (ttybuf.st_uid)->pw_name) == NULL) { fprintf (stderr, "I have no idea who you are.\n"); exit (EXIT_FAILURE); } strncpy (user.from, getpwuid (ttybuf.st_uid)->pw_name, BUFSIZ - 1); } else { fprintf (stderr, "Couldn't stat %s\n", ttyname (0)); exit (EXIT_FAILURE); } } else { fprintf (stderr, "%s: couldn't get your controlling terminal.\n", progname); exit (EXIT_FAILURE); } user.pw = getpwuid ((uid_t) getuid ()); snprintf (user.home.str, BUFSIZ - 1, "HOME=%s", user.pw->pw_dir); strncpy (user.to_home.str, user.pw->pw_dir, BUFSIZ - 1); snprintf (user.term.str, BUFSIZ - 1, "TERM=%s", user.term.ptr); #ifdef HAVE_GETUSERSHELL if ((user.shell.ptr = getenv ("SHELL")) == NULL) user.shell.ptr = user.pw->pw_shell; /* check against /etc/shells to make sure it's a real shell */ setusershell (); while ((user.vshell = (char *) getusershell ()) != (char *) 0) { if (strcmp (user.shell.ptr, user.vshell) == 0) valid = 1; } endusershell (); if (valid != 1) { if (user.shell.ptr == NULL) { fprintf (stderr, "Could not determine a valid shell.\n"); if (sudosh_option.priority != -1) mysyslog (sudosh_option.priority, "Could not determine a valid shell"); exit (EXIT_FAILURE); } else { fprintf (stderr, "%s is not in /etc/shells\n", user.shell.ptr); mysyslog (sudosh_option.priority, "%s,%s: %s is not in /etc/shells", user.from, ttyname (0), user.shell.ptr); exit (EXIT_FAILURE); } } if (stat ((const char *) user.shell.ptr, &s) == -1) { fprintf (stderr, "Shell %s doesn't exist.\n", user.shell.ptr); if (sudosh_option.priority != -1) mysyslog (sudosh_option.priority, "%s,%s: shell %s doesn't exist.", user.from, ttyname (0), user.shell.ptr); exit (EXIT_FAILURE); } #else user.shell.ptr = user.pw->pw_shell; #endif /* HAVE_GETUSERSHELL */ if (loginshell) user.shell.ptr = sudosh_option.defshell; snprintf (script.name, (size_t) BUFSIZ - 1, "%s/%s%c%s%cscript%c%i%c%s", sudosh_option.logdir, user.from, sudosh_option.fdl, user.to, sudosh_option.fdl, sudosh_option.fdl, (int) now, sudosh_option.fdl, rand); snprintf (timing.name, (size_t) BUFSIZ - 1, "%s/%s%c%s%ctime%c%i%c%s", sudosh_option.logdir, user.from, sudosh_option.fdl, user.to, sudosh_option.fdl, sudosh_option.fdl, (int) now, sudosh_option.fdl, rand); #ifdef RECORDINPUT snprintf (input.name, (size_t) BUFSIZ - 1, "%s/%s%c%s%cinput%c%i%c%s", sudosh_option.logdir, user.from, sudosh_option.fdl, user.to, sudosh_option.fdl, sudosh_option.fdl, (int) now, sudosh_option.fdl, rand); #endif snprintf (start_msg, BUFSIZ - 1, "starting session for %s as %s, tty %s, shell %s", user.from, user.to, ttyname (0), user.shell.ptr); set_perms_and_open_file(&script); set_perms_and_open_file(&timing); #ifdef RECORDINPUT set_perms_and_open_file(&input); #endif if (sudosh_option.priority != -1) mysyslog (sudosh_option.priority, start_msg); rawmode (0); if (findms (&pspair) < 0) { perror ("open pty failed"); bye (EXIT_FAILURE); } switch (fork ()) { case 0: close (pspair.mfd); prepchild (&pspair); case -1: perror ("fork failed"); bye (EXIT_FAILURE); default: close (pspair.sfd); } orig_euid = geteuid(); if (seteuid (getuid ()) != 0) { perror ("setuid failed"); bye (EXIT_FAILURE); } memset (&sawinch, 0, sizeof sawinch); sawinch.sa_handler = newwinsize; sawinch.sa_flags = SA_RESTART; sigaction (SIGWINCH, &sawinch, (struct sigaction *) 0); memset (&saterm, 0, sizeof saterm); saterm.sa_handler = bye; sigaction (SIGTERM, &sawinch, (struct sigaction *) 0); memset (&sachild, 0, sizeof sachild); sachild.sa_handler = bye; sigaction (SIGCHLD, &sachild, (struct sigaction *) 0); oldtime = time (NULL); while (n > 0) { fd_set readfds; FD_ZERO (&readfds); FD_SET (pspair.mfd, &readfds); FD_SET (0, &readfds); gettimeofday ((struct timeval *) &tv, NULL); if (select (pspair.mfd + 1, &readfds, (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0) < 0) { if (errno == EINTR) continue; perror ("select"); bye (EXIT_FAILURE); } if (FD_ISSET (pspair.mfd, &readfds)) { if ((n = read (pspair.mfd, iobuf, sizeof (iobuf))) > 0) { DO_WRITE (1, iobuf, n); script.bytes += DO_WRITE (script.fd, iobuf, n); } newtime = tv.tv_sec + (double) tv.tv_usec / 1000000; snprintf (timing.str, BUFSIZ - 1, "%f %i\n", newtime - oldtime, n); timing.bytes += DO_WRITE (timing.fd, &timing.str, strlen (timing.str)); oldtime = newtime; } if (FD_ISSET (0, &readfds)) { if ((n = read (0, iobuf, BUFSIZ)) > 0) { DO_WRITE (pspair.mfd, iobuf, n); #ifdef RECORDINPUT switch (*iobuf) { case '\r': snprintf (input.str, BUFSIZ - 1, "\n"); break; case 0x003: snprintf (input.str, BUFSIZ - 1, "(CTRL-C)"); break; case 0x004: snprintf (input.str, BUFSIZ - 1, "(CTRL-D)\n"); break; case 0x1a: snprintf (input.str, BUFSIZ - 1, "(CTRL-Z)\n"); break; case 0x1b: snprintf (input.str, BUFSIZ - 1, "(ESC)"); break; default: DO_WRITE (input.fd, iobuf, 1); written = 1; break; } if (written == 0) { DO_WRITE (input.fd, &input.str, strlen (input.str)); } #endif } } } bye (EXIT_SUCCESS); return (0); }
/* * logger -- read and log utility * * Reads from an input and arranges to write the result on the system * log. */ int main(int argc, char **argv) { int ch, logflags, pri, prio_prefix; char *tag, buf[1024]; char *usock = NULL; char *server = NULL; char *port = NULL; int LogSock = -1, socket_type = ALL_TYPES; #ifdef HAVE_LIBSYSTEMD FILE *jfd = NULL; #endif static const struct option longopts[] = { { "id", no_argument, 0, 'i' }, { "stderr", no_argument, 0, 's' }, { "file", required_argument, 0, 'f' }, { "priority", required_argument, 0, 'p' }, { "tag", required_argument, 0, 't' }, { "socket", required_argument, 0, 'u' }, { "udp", no_argument, 0, 'd' }, { "tcp", no_argument, 0, 'T' }, { "server", required_argument, 0, 'n' }, { "port", required_argument, 0, 'P' }, { "version", no_argument, 0, 'V' }, { "help", no_argument, 0, 'h' }, { "prio-prefix", no_argument, 0, OPT_PRIO_PREFIX }, #ifdef HAVE_LIBSYSTEMD { "journald", optional_argument, 0, OPT_JOURNALD }, #endif { NULL, 0, 0, 0 } }; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); atexit(close_stdout); tag = NULL; pri = LOG_NOTICE; logflags = 0; prio_prefix = 0; while ((ch = getopt_long(argc, argv, "f:ip:st:u:dTn:P:Vh", longopts, NULL)) != -1) { switch (ch) { case 'f': /* file to log */ if (freopen(optarg, "r", stdin) == NULL) err(EXIT_FAILURE, _("file %s"), optarg); break; case 'i': /* log process id also */ logflags |= LOG_PID; break; case 'p': /* priority */ pri = pencode(optarg); break; case 's': /* log to standard error */ logflags |= LOG_PERROR; break; case 't': /* tag */ tag = optarg; break; case 'u': /* unix socket */ usock = optarg; break; case 'd': socket_type = TYPE_UDP; break; case 'T': socket_type = TYPE_TCP; break; case 'n': server = optarg; break; case 'P': port = optarg; break; case 'V': printf(UTIL_LINUX_VERSION); exit(EXIT_SUCCESS); case 'h': usage(stdout); case OPT_PRIO_PREFIX: prio_prefix = 1; break; #ifdef HAVE_LIBSYSTEMD case OPT_JOURNALD: if (optarg) { jfd = fopen(optarg, "r"); if (!jfd) err(EXIT_FAILURE, _("cannot open %s"), optarg); } else jfd = stdin; break; #endif case '?': default: usage(stderr); } } argc -= optind; argv += optind; /* setup for logging */ #ifdef HAVE_LIBSYSTEMD if (jfd) { int ret = journald_entry(jfd); if (stdin != jfd) fclose(jfd); return ret ? EXIT_FAILURE : EXIT_SUCCESS; } #endif if (server) LogSock = inet_socket(server, port, socket_type); else if (usock) LogSock = unix_socket(usock, socket_type); else openlog(tag ? tag : getlogin(), logflags, 0); /* log input line if appropriate */ if (argc > 0) { register char *p, *endp; size_t len; for (p = buf, endp = buf + sizeof(buf) - 2; *argv;) { len = strlen(*argv); if (p + len > endp && p > buf) { if (!usock && !server) syslog(pri, "%s", buf); else mysyslog(LogSock, logflags, pri, tag, buf); p = buf; } if (len > sizeof(buf) - 1) { if (!usock && !server) syslog(pri, "%s", *argv++); else mysyslog(LogSock, logflags, pri, tag, *argv++); } else { if (p != buf) *p++ = ' '; memmove(p, *argv++, len); *(p += len) = '\0'; } } if (p != buf) { if (!usock && !server) syslog(pri, "%s", buf); else mysyslog(LogSock, logflags, pri, tag, buf); } } else { char *msg; int default_priority = pri; while (fgets(buf, sizeof(buf), stdin) != NULL) { /* glibc is buggy and adds an additional newline, so we have to remove it here until glibc is fixed */ int len = strlen(buf); if (len > 0 && buf[len - 1] == '\n') buf[len - 1] = '\0'; msg = buf; pri = default_priority; if (prio_prefix && msg[0] == '<') msg = get_prio_prefix(msg, &pri); if (!usock && !server) syslog(pri, "%s", msg); else mysyslog(LogSock, logflags, pri, tag, msg); } } if (!usock && !server) closelog(); else close(LogSock); return EXIT_SUCCESS; }
void get_options(int argc, char *const argv[]) { extern u_char *logfile, *lockfile, *user, *group, *ifstring; int opt; while ((opt = getopt_long(argc, argv, opts, longopts, NULL)) != EOF) { switch (opt) { case 10: enable(optarg, LOG_TCP); break; case 11: enable(optarg, LOG_UDP); break; case 12: enable(optarg, LOG_ICMP); break; case 13: facility = get_facility(optarg); break; case 14: priority = get_priority(optarg); break; case 15: if (lockfile != NULL) free(lockfile); lockfile = xstrdup(optarg); break; case 'w': enable(optarg, LOG_IP); break; case 'd': flags |= IGNORE_NS; break; case 'u': if (user != NULL) free(user); user = xstrdup(optarg); break; case 'g': if (group != NULL) free(group); group = xstrdup(optarg); break; case 'k': kill_iplog(15, lockfile); break; case 'l': if (opt_enabled(LOG_STDOUT)) { mysyslog("Warning: Overriding --stdout"); flags &= ~LOG_STDOUT; } else if (logfile != NULL) free(logfile); logfile = xstrdup(optarg); break; case 'L': if (logfile != NULL) { mysyslog("Warning: Overriding --logfile"); xfree(logfile); } flags |= LOG_STDOUT; break; case 'm': enable(optarg, SCANS_ONLY); break; case 'o': flags |= NO_FORK; break; case 'c': enable(optarg, DNS_CACHE); break; case 'y': enable(optarg, LOG_FRAG); break; case 'a': flags |= (PROMISC | LOG_DEST); if (pcap_network != NULL) free(pcap_network); pcap_network = xstrdup(optarg); break; case 'D': enable(optarg, LOG_DEST); break; case 'e': #ifdef __linux__ enable(optarg, GET_IDENT); #else mysyslog("Ident lookups are only supported on Linux."); #endif break; case 'T': enable(optarg, TCP_RES); break; case 'U': enable(optarg, UDP_RES); break; case 'V': enable(optarg, VERBOSE); break; case 'I': enable(optarg, ICMP_RES); break; case 'S': enable(optarg, SMURF); break; case 'b': enable(optarg, BOGUS); break; case 'P': enable(optarg, PING_FLOOD); break; case 'p': enable(optarg, PORTSCAN); break; case 'x': enable(optarg, XMAS_SCAN); break; case 'f': enable(optarg, FIN_SCAN); break; case 'q': enable(optarg, SYN_SCAN); break; case 'F': enable(optarg, UDP_SCAN); break; case 'N': flags |= NO_RESOLV; break; case 'n': enable(optarg, NULL_SCAN); break; case 's': enable(optarg, SYN_FLOOD); break; case 't': enable(optarg, TRACEROUTE); break; case 'i': if (ifstring != NULL) free(ifstring); ifstring = xstrdup(optarg); break; case 'R': kill_iplog(1, lockfile); break; case 'z': enable(optarg, FOOL_NMAP); break; case 'v': mysyslog("iplog version %s\nby %s\n%s", VERSION, AUTHORS, WEBPAGE); exit(0); case 'h': default: print_help(); break; } } }
int main (int argc, char const * argv []) { static char const * optv [] = { "write a message to the system logging facility", "[message]", "b:def:i:p:ns:t", "b s\tidentity is the basename of s ", "e\techo messages on stderr", "f s\tmessage filename", "i s\tidentity string", "p s\tpriority in facility.severity format", "n\tinclude PID number", "d\tuse datagrams", "s s\tsocket filename", "t\tsend test messages", (char const *) (0) }; char message [TEXTLINE_MAX]; char * bp = message; char const * socketname = (char *) (0); char const * identity = (char *) (0); int priority = SYSLOG_USER | SYSLOG_INFO; code_t sockettype = SOCK_STREAM; flag_t options = (flag_t) (0); file_t fd = (file_t) (-1); int c; while (~ (c = getoptv (argc, argv, optv))) { switch (c) { case 'b': for (identity = optarg; * optarg != (char) (0); optarg++) { if (* optarg == PATH_C_EXTENDER) { identity = optarg + 1; } } break; case 'd': sockettype = SOCK_DGRAM; break; case 'e': _setbits (options, SYSLOG_PERROR); break; case 'f': if (freopen (optarg, "rb", stdin) == (FILE *) (0)) { error (1, errno, "%s", optarg); } break; case 'i': identity = optarg; break; case 'n': _setbits (options, SYSLOG_PROCESS); break; case 'p': priority = syslog_encode (optarg); break; case 's': socketname = optarg; break; case 't': mysyslogtest (priority); exit (0); default: break; } } argc -= optind; argv += optind; fclose (stdout); if (socketname) { fd = myopenlog (socketname, sockettype); } else { openlog (identity, options, priority); } if (! argc) { while ((c = getc (stdin)) != EOF) { if (nobreak (c)) { if ((unsigned) (bp - message) < STRLEN (message)) { * bp++ = c; } } else { * bp = (char) (0); if (socketname) { mysyslog (fd, options, priority, identity, message); } else { syslog (priority, "%s", message); } bp = message; } } } else { for (bp = message; (argc) && (* argv); * bp++ = ' ') { char const * string; for (string = * argv; * string; string++) { if ((unsigned) (bp - message) < STRLEN (message)) { * bp++ = * string; } } argc--; argv++; } if (bp > message) { bp--; } * bp = (char) (0); if (socketname) { mysyslog (fd, options, priority, identity, message); } else { syslog (priority, "%s", message); } } if (socketname) { close (fd); } else { closelog (); } exit (0); }
static void print_help(void) { mysyslog( "Usage: " PACKAGE " [options] (\"*\" Denotes enabled by default)\n" "--user or -u <user|UID> Run as specified the user or UID.\n" "--group or -g <group|GID> Run with specified the group or GID.\n" "--logfile or -l <file> Log to <file>.\n" "--pid-file <file> Use <file> as the pid file.\n" "--ignore or -d Ignore DNS traffic from nameservers listed in\n" " /etc/resolv.conf.\n" "--interface or -i <if0,...,ifN> Listen on the specified interface(s).\n" "--promisc or -a <network> Log traffic to all hosts on <network>.\n" "--kill or -k Kill iplog, if it is running.\n" "--restart or -R Restart iplog, if it is running.\n" "--no-fork or -o Run in the foreground.\n" "--stdout or -L Log to stdout.\n" "--help or -h This help screen.\n" "--version or -v Print version information and exit.\n" "\n" "--facility <facility> Use the specified syslog facility.\n" "--priority <priority> Use the specified syslog priority.\n" "\n" "--tcp[=true|false|toggle] %cLog TCP traffic.\n" "--udp[=true|false|toggle] %cLog UDP traffic.\n" "--icmp[=true|false|toggle] %cLog ICMP traffic.\n" "\n" "--log-ip[=true|false|toggle] or -w %cLog IP along with hostname.\n" "--log-dest[=true|false|toggle] or -D %cLog the destination of traffic.\n" "--dns-cache[=true|false|toggle] or -c %cUse the built-in DNS cache.\n" "--get-ident[=true|false|toggle] or -e %cGet ident info on connections\n" " to listening ports.\n" "\n" "--tcp-resolve[=true|false|toggle] or -T %cResolve IPs of TCP traffic.\n" "--udp-resolve[=true|false|toggle] or -U %cResolve IPs of UDP traffic.\n" "--icmp-resolve[=true|false|toggle] or -I %cResolve IPs of ICMP traffic.\n" "--disable-resolver or -N %cDo not resolve any IPs.\n" "\n" "--verbose[=true|false|toggle] or -V %cBe verbose.\n" "--fool-nmap[=true|false|toggle] or -z %cFool nmap's OS detection.\n" "--scans-only[=true|false|toggle] or -m %cOnly log scans.\n" "--detect-syn-flood[=true|false|toggle] or -s %cStop resolving IPs if a\n" " SYN flood is detected.\n" "\n" "--log-frag[=true|false|toggle] or -y %cLog fragment attacks.\n" "--log-traceroute[=true|false|toggle] or -t %cLog traceroutes.\n" "--log-ping-flood[=true|false|toggle] or -P %cLog ICMP ping floods.\n" "--log-smurf[=true|false|toggle] or -S %cLog smurf attacks.\n" "--log-bogus[=true|false|toggle] or -b %cLog bogus TCP flags.\n" "--log-portscan[=true|false|toggle] or -p %cLog port scans.\n" "--log-udp-scan[=true|false|toggle] or -F %cLog UDP scans/floods.\n" "--log-fin-scan[=true|false|toggle] or -f %cLog FIN scans.\n" "--log-syn-scan[=true|false|toggle] or -q %cLog SYN scans.\n" "--log-xmas-scan[=true|false|toggle] or -x %cLog Xmas scans.\n" "--log-null-scan[=true|false|toggle] or -n %cLog null scans.", IS_DEFAULT(LOG_TCP), IS_DEFAULT(LOG_UDP), IS_DEFAULT(LOG_ICMP), IS_DEFAULT(LOG_IP), IS_DEFAULT(LOG_DEST), IS_DEFAULT(DNS_CACHE), IS_DEFAULT(GET_IDENT), IS_DEFAULT(TCP_RES), IS_DEFAULT(UDP_RES), IS_DEFAULT(ICMP_RES), IS_DEFAULT(NO_RESOLV), IS_DEFAULT(VERBOSE), IS_DEFAULT(FOOL_NMAP), IS_DEFAULT(SCANS_ONLY), IS_DEFAULT(SYN_FLOOD), IS_DEFAULT(LOG_FRAG), IS_DEFAULT(TRACEROUTE), IS_DEFAULT(PING_FLOOD), IS_DEFAULT(SMURF), IS_DEFAULT(BOGUS), IS_DEFAULT(PORTSCAN), IS_DEFAULT(UDP_SCAN), IS_DEFAULT(FIN_SCAN), IS_DEFAULT(SYN_SCAN), IS_DEFAULT(XMAS_SCAN), IS_DEFAULT(NULL_SCAN)); exit(0); }
/* * Send a message to MAILTO user */ static void send_mail(const char *fmt, ...) { FILE *mail; char *p; int fd, pfd[2], status; pid_t pid, rv; sigaction_t sa; va_list ap; #ifndef NO_ROOT_MAILER static char *root_envp[] = { "HOME=/", "PATH=/usr/bin:/bin:/usr/sbin:/sbin", "LOGNAME=root", "USERNAME=root", "USER=root", NULL }; #endif /* NO_ROOT_MAILER */ /* Just return if mailer is disabled. */ if (!def_mailerpath || !def_mailto) return; /* Fork and return, child will daemonize. */ switch (pid = fork()) { case -1: /* Error. */ error(1, _("unable to fork")); break; case 0: /* Child. */ switch (pid = fork()) { case -1: /* Error. */ mysyslog(LOG_ERR, _("unable to fork: %m")); _exit(1); case 0: /* Grandchild continues below. */ break; default: /* Parent will wait for us. */ _exit(0); } break; default: /* Parent. */ do { rv = waitpid(pid, &status, 0); } while (rv == -1 && errno == EINTR); return; } /* Daemonize - disassociate from session/tty. */ if (setsid() == -1) warning("setsid"); if (chdir("/") == -1) warning("chdir(/)"); if ((fd = open(_PATH_DEVNULL, O_RDWR, 0644)) != -1) { (void) dup2(fd, STDIN_FILENO); (void) dup2(fd, STDOUT_FILENO); (void) dup2(fd, STDERR_FILENO); } #ifdef HAVE_SETLOCALE if (!setlocale(LC_ALL, def_sudoers_locale)) { setlocale(LC_ALL, "C"); efree(def_sudoers_locale); def_sudoers_locale = estrdup("C"); } #endif /* HAVE_SETLOCALE */ /* Close password, group and other fds so we don't leak. */ sudo_endpwent(); sudo_endgrent(); closefrom(STDERR_FILENO + 1); /* Ignore SIGPIPE in case mailer exits prematurely (or is missing). */ zero_bytes(&sa, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_INTERRUPT; sa.sa_handler = SIG_IGN; (void) sigaction(SIGPIPE, &sa, NULL); if (pipe(pfd) == -1) { mysyslog(LOG_ERR, _("unable to open pipe: %m")); _exit(1); } switch (pid = fork()) { case -1: /* Error. */ mysyslog(LOG_ERR, _("unable to fork: %m")); _exit(1); break; case 0: { char *argv[MAX_MAILFLAGS + 1]; char *mpath, *mflags; int i; /* Child, set stdin to output side of the pipe */ if (pfd[0] != STDIN_FILENO) { if (dup2(pfd[0], STDIN_FILENO) == -1) { mysyslog(LOG_ERR, _("unable to dup stdin: %m")); _exit(127); } (void) close(pfd[0]); } (void) close(pfd[1]); /* Build up an argv based on the mailer path and flags */ mflags = estrdup(def_mailerflags); mpath = estrdup(def_mailerpath); if ((argv[0] = strrchr(mpath, ' '))) argv[0]++; else argv[0] = mpath; i = 1; if ((p = strtok(mflags, " \t"))) { do { argv[i] = p; } while (++i < MAX_MAILFLAGS && (p = strtok(NULL, " \t"))); } argv[i] = NULL; /* * Depending on the config, either run the mailer as root * (so user cannot kill it) or as the user (for the paranoid). */ #ifndef NO_ROOT_MAILER set_perms(PERM_ROOT|PERM_NOEXIT); execve(mpath, argv, root_envp); #else set_perms(PERM_FULL_USER|PERM_NOEXIT); execv(mpath, argv); #endif /* NO_ROOT_MAILER */ mysyslog(LOG_ERR, _("unable to execute %s: %m"), mpath); _exit(127); } break; } (void) close(pfd[0]); mail = fdopen(pfd[1], "w"); /* Pipes are all setup, send message. */ (void) fprintf(mail, "To: %s\nFrom: %s\nAuto-Submitted: %s\nSubject: ", def_mailto, def_mailfrom ? def_mailfrom : user_name, "auto-generated"); for (p = def_mailsub; *p; p++) { /* Expand escapes in the subject */ if (*p == '%' && *(p+1) != '%') { switch (*(++p)) { case 'h': (void) fputs(user_host, mail); break; case 'u': (void) fputs(user_name, mail); break; default: p--; break; } } else (void) fputc(*p, mail); } #ifdef HAVE_NL_LANGINFO if (strcmp(def_sudoers_locale, "C") != 0) (void) fprintf(mail, "\nContent-Type: text/plain; charset=\"%s\"\nContent-Transfer-Encoding: 8bit", nl_langinfo(CODESET)); #endif /* HAVE_NL_LANGINFO */ (void) fprintf(mail, "\n\n%s : %s : %s : ", user_host, get_timestr(time(NULL), def_log_year), user_name); va_start(ap, fmt); (void) vfprintf(mail, fmt, ap); va_end(ap); fputs("\n\n", mail); fclose(mail); do { rv = waitpid(pid, &status, 0); } while (rv == -1 && errno == EINTR); _exit(0); }
/* * logger -- read and log utility * Reads from an input and arranges to write the result on the system log. */ int main (int argc, char **argv) { int ch, logflags, pri; char *tag, buf[MAX_LINE]; char *usock = NULL; long timeout_ms = 100; long timeout_sec; long timeout_usec; int indent_mode = 0; char *udpserver = NULL; int LogSock = -1; long tmpport; static const struct option longopts[] = { { "id", no_argument, 0, 'i' }, { "stderr", no_argument, 0, 's' }, { "file", required_argument, 0, 'f' }, { "priority", required_argument, 0, 'p' }, { "tag", required_argument, 0, 't' }, { "socket", required_argument, 0, 'u' }, { "udp", no_argument, 0, 'd' }, { "server", required_argument, 0, 'n' }, { "port", required_argument, 0, 'P' }, { "indent", required_argument, 0, 'I' }, { "version", no_argument, 0, 'V' }, { "help", no_argument, 0, 'h' }, { NULL, 0, 0, 0 } }; tag = NULL; pri = LOG_NOTICE; logflags = 0; while ((ch = getopt_long(argc, argv, "f:ip:st:u:dI:n:P:Vh", longopts, NULL)) != -1) { switch((char) ch) { case 'f': /* file to log */ if (freopen(optarg, "r", stdin) == NULL) err(EXIT_FAILURE, "file %s", optarg); break; case 'i': /* log process id also */ logflags |= LOG_PID; break; case 'p': /* priority */ pri = pencode(optarg); break; case 's': /* log to standard error */ logflags |= LOG_PERROR; break; case 't': /* tag */ tag = optarg; break; case 'u': /* unix socket */ usock = optarg; break; case 'd': optd = 1; /* use datagrams */ break; case 'n': /* udp socket */ optd = 1; /* use datagrams because udp */ udpserver = optarg; break; case 'P': /* change udp port */ tmpport = strtol_or_err(optarg, "failed to parse port number"); if (tmpport < 0 || 65535 < tmpport) { errx(EXIT_FAILURE, "port `%ld' out of range", tmpport); } udpport = (int) tmpport; break; case 'V': printf("%s %s\n", PROGRAM_NAME, PROGRAM_VERSION); exit(EXIT_SUCCESS); case 'I': indent_mode = 1; timeout_ms = strtol_or_err(optarg, "failed to parse timeout number"); if (timeout_ms < 1) { errx(EXIT_FAILURE, "Invalid value for timeout %li", timeout_ms); } break; case 'h': usage(stdout); case '?': default: usage(stderr); } } argc -= optind; argv += optind; /* setup for logging */ if (!usock && !udpserver) { openlog(tag ? tag : getlogin(), logflags, 0); } else if (udpserver) { LogSock = udpopenlog(udpserver, udpport); } else { LogSock = myopenlog(usock); } (void) fclose(stdout); /* log input line if appropriate */ if (argc > 0) { char *p, *endp; size_t len; for (p = buf, endp = buf + sizeof(buf) - 2; *argv;) { len = strlen(*argv); if (p + len > endp && p > buf) { if (!usock && !udpserver) { syslog(pri, "%s", buf); } else { mysyslog(LogSock, logflags, pri, tag, buf); } p = buf; } if (len > sizeof(buf) - 1) { if (!usock && !udpserver) { syslog(pri, "%s", *argv++); } else { mysyslog(LogSock, logflags, pri, tag, *argv++); } } else { if (p != buf) { *p++ = ' '; } memmove(p, *argv++, len); *(p += len) = '\0'; } } if (p != buf) { if (!usock && !udpserver) { syslog(pri, "%s", buf); } else { mysyslog(LogSock, logflags, pri, tag, buf); } } } else if (indent_mode) { int len; timeout_sec = timeout_ms / 1000; timeout_usec = (timeout_ms % 1000) * 1000; while ((len = readBlock(buf, MAX_LINE, timeout_sec, timeout_usec)) != EOF) { //fprintf(stderr, "Got buf %i\n", len); if (len > 0 && buf[len - 1] == '\n') { buf[len - 1] = '\0'; } if (!usock && !udpserver) { syslog(pri, "%s", buf); } else { mysyslog(LogSock, logflags, pri, tag, buf); } } } else { while (fgets(buf, sizeof(buf), stdin) != NULL) { /* glibc is buggy and adds an additional newline, so we have to remove it here until glibc is fixed */ int len = strlen(buf); if (len > 0 && buf[len - 1] == '\n') { buf[len - 1] = '\0'; } if (!usock && !udpserver) { syslog(pri, "%s", buf); } else { mysyslog(LogSock, logflags, pri, tag, buf); } } } if (!usock && !udpserver) { closelog(); } else { close(LogSock); } return EXIT_SUCCESS; }
static int handle_login(const char *user) { int idx = 0, ret; int existed = 1; size_t ulen = strlen("user/") + strlen(user); size_t len = ulen + 50; // Just make sure there's room for "user/$user or an <integer>" uid_t uid = 0; gid_t gid = 0; nih_local char *cg = NIH_MUST( nih_alloc(NULL, len) ); if (!get_uid_gid(user, &uid, &gid)) { mysyslog(LOG_ERR, "failed to get uid and gid for %s\n", user); return PAM_SESSION_ERR; } memset(cg, 0, len); strcpy(cg, user); ret = snprintf(cg, len, "user/%s", user); if (ret < 0 || ret >= len) return PAM_SESSION_ERR; if (!cgm_create(cg, &existed)) { mysyslog(LOG_ERR, "failed to create cgroup %s\n", cg); return PAM_SESSION_ERR; } if (existed == 0) { if (!cgm_autoremove(cg)) { mysyslog(LOG_ERR, "Warning: failed to set autoremove on %s\n", cg); } } if (!cgm_enter(cg)) { mysyslog(LOG_ERR, "failed to enter cgroup %s\n", cg); return PAM_SESSION_ERR; } while (idx >= 0) { sprintf(cg, "%d", idx); if (!cgm_create(cg, &existed)) { mysyslog(LOG_ERR, "failed to create a user cgroup\n"); return PAM_SESSION_ERR; } if (existed == 1) { idx++; continue; } if (!cgm_chown(cg, uid, gid)) { mysyslog(LOG_ERR, "Warning: failed to chown %s\n", cg); } if (!cgm_autoremove(cg)) { mysyslog(LOG_ERR, "Warning: failed to set autoremove on %s\n", cg); } if (!cgm_enter(cg)) { mysyslog(LOG_ERR, "failed to enter user cgroup %s\n", cg); return PAM_SESSION_ERR; } break; } return PAM_SUCCESS; }