📄 socdemon.c
字号:
/* * Socket Demon. * - A little program that waits on a internet port and * handles interactive commands. * Most of the routines are taken out of "Unix Network Programming" * by W. Richard Stevens, Prentice Hall, 1990. * * History: * 1994: * Jan. 14 - Initial program completed. * Jan. 17 - Added in nil command (if you just press enter) * - Added in "?" to be the same as help * - Added in the "bye", "ls", "pwd", and "cd" commands. * - Added in lotsa comments * - Added the 'ver' command. * - Added in support for the -port, -log and -command * command line options. * - Added in the 'die' command. * - Added logging of connects, disconnects, die's, and * bad passwords. * Apr. 07 - Changed the password to be encrypted so it cannot be * discovered with a strings(1) command. * - Added the 'id' command. * - Call setuid if uid != euid (so that if program is setuid root * - we can take advantage of the priviledge). * - Took out the annoying uid listing at login * Apr. 11 - Added a debug mode, and moved most of the verbose FTP style * comments to that mode, leaving normal mode more unix-ish. * - Added in a uname command * - Changed the output format of several commands to look more * unix-ish * Apr. 13 - Split the program up in to a bunch of different files and * made a make file for it. - Speeds up development and * makes if easier to change.. * Apr. 14 - Added new commands, cp, mv, rm * - Redirected stdin, stdout and stderr to the client socket. * - Added a shell! * Apr. 15 - Added new commands, who, w, ps, chmod, chgrp, chown, cat, * create*/#include "socdemon.h"#include "socketio.h"#include "soclog.h"/* * print_usage() * - prints the program name, version, and date, and also * the program parameters. See socdemon.h for all their * definitions.*/void print_usage() { int i; fprintf(stdout,"%s ver %s, %s.\n",SOCDEMON_NAME,SOCDEMON_VER,SOCDEMON_DATE); fprintf(stdout,"usage: %s [option] [option]...\n",program_name); fprintf(stdout,"where [option] is one of:\n"); for (i=0;i<parm_nil;i+=2) { fprintf(stdout," %8.8s - %s\n",parm_table[i],parm_table[i+1]); }}/* * socket_demon_shutdown() * - shuts down the internet socket (the one created by * the original parent, not the descriptors created by the * accept() call). This is called before the program terminates, * (under an error condition, or when a SIGTERM signal is caught).*/void socket_demon_shutdown() { soc_fprintf(stdout,"%s: Shutting down internet socket...",SOCDEMON_NAME); if (shutdown(socket_descriptor, 2) != 0) { soc_fprintf(stdout,"\n"); soc_fprintf(stderr,"ERROR(%d): Unable to shutdown socket [%d].\n", CANT_SHUTDOWN_SOCKET, errno); /* dont exit, try and close it */ } soc_fprintf(stdout,"done.\n"); soc_fprintf(stdout,"%s: Closing internet socket...",SOCDEMON_NAME); if (close(socket_descriptor) != 0) { soc_fprintf(stdout,"\n"); soc_fprintf(stderr,"ERROR(%d): Unable to close socket [%d].\n", CANT_CLOSE_SOCKET, errno); exit(CANT_CLOSE_SOCKET); } soc_fprintf(stdout,"done.\n");}/* * socket_demon_death_action() * - this is the signal handler for the signals SIGTERM and SIGKILL, * however, I don't think it catches the SIGKILL's, so always kill * with a plain kill, and never a -9 parm.*/void socket_demon_death_action() { soc_fprintf(stdout,"%s: Received shutdown notice.\n",SOCDEMON_NAME); socket_demon_shutdown(); soc_fprintf(stdout,"%s: Exiting..\n",SOCDEMON_NAME); exit(0);}/* * soc_demon_main_proc() * - This is sorta the main process that the forked process * handling the incoming user sits in. It waits for input * and then calls the handler proc for that action. * - The daemon forks, the parent executing this routine, and * the child returning to wait on the port. The benefits of * doing it this way, instead of having the parent go back * to wait on the port is that * i) You don't get defunct processes in you process tables * ii) The process id of the main daemon changes after every * use.*/void soc_demon_main_proc() { char in_msg[MAX_INPUT_LEN]; char in_parm[MAX_INPUT_LEN]; char *cmd_ptr; char out_msg[MAX_OUTPUT_LEN]; int msg_len = 0; int i; for (;;) { tell_user(client_descriptor, SOCDEMON_PROMPT); msg_len = soc_read(client_descriptor, in_msg, MAX_INPUT_LEN); if (msg_len < 0) { soc_fprintf(stderr,"ERROR(%d): Error reading socket input [%d:%d].\n", SOCKET_INPUT_ERROR, msg_len, errno); return; } if (in_msg[strlen(in_msg)-1] == '\n') { in_msg[strlen(in_msg)-2] = 0; strcpy(in_parm,in_msg); cmd_ptr = (char *) strtok(in_msg," "); i = strlen(in_msg); cmd_ptr = &in_parm[i]; strcpy(in_parm,cmd_ptr); if (in_parm[0] != 0) { cmd_ptr = &in_parm[1]; strcpy(in_parm,cmd_ptr); } for (i=0;i<strlen(in_msg);i++) { in_msg[i] = toupper(in_msg[i]); }#ifdef LOG_TO_DEATH log_command(in_msg);#endif if ((!strcmp(in_msg,command_table[cmd_help])) || (!strcmp(in_msg,command_table[cmd_qstn]))) { tell_user(client_descriptor, "%3.3d - %s", valid_commands, out_table[valid_commands]); for (i=0;i<=cmd_nil;i+=2) { tell_user(client_descriptor, " %-6.6s - %s\n", command_table[i],command_table[i+1]); } } else if ((!strcmp(in_msg,command_table[cmd_quit])) || (!strcmp(in_msg,command_table[cmd_bye]))) { tell_user(client_descriptor, "%3.3d - %s", goodbye_str, out_table[goodbye_str]); break; } else if (!strcmp(in_msg,command_table[cmd_ver])) { report_version(); } else if (!strcmp(in_msg,command_table[cmd_pwd])) { get_pwd(); } else if (!strcmp(in_msg,command_table[cmd_whoami])) { who_am_i(); } else if (!strcmp(in_msg,command_table[cmd_id])) { get_id(); } else if (!strcmp(in_msg,command_table[cmd_cp])) { do_cp(in_parm); } else if (!strcmp(in_msg,command_table[cmd_rm])) { do_rm(in_parm); } else if (!strcmp(in_msg,command_table[cmd_ps])) { do_ps(in_parm); } else if (!strcmp(in_msg,command_table[cmd_w])) { do_unix_command("w"); } else if (!strcmp(in_msg,command_table[cmd_who])) { do_unix_command("who"); } else if (!strcmp(in_msg,command_table[cmd_create])) { do_create(in_parm); } else if (!strcmp(in_msg,command_table[cmd_chmod])) { do_chmod(in_parm); } else if (!strcmp(in_msg,command_table[cmd_chown])) { do_chown(in_parm); } else if (!strcmp(in_msg,command_table[cmd_chgrp])) { do_chgrp(in_parm); } else if (!strcmp(in_msg,command_table[cmd_mv])) { do_mv(in_parm); } else if (!strcmp(in_msg,command_table[cmd_cat])) { do_cat(in_parm); } else if (!strcmp(in_msg,command_table[cmd_shell])) { do_shell(); } else if (!strcmp(in_msg,command_table[cmd_uname])) { strcpy(out_msg,"uname"); if (in_parm[0] != 0) { strcat(out_msg," "); strcat(out_msg,in_parm); } do_unix_command(out_msg); } else if (!strcmp(in_msg,command_table[cmd_cd])) { ch_dir(in_parm); } else if (!strcmp(in_msg,command_table[cmd_die])) { /* ok, to kill both the client and the server, we */ /* first kill our parent, then ourselves... when */ /* our parent get's the TERM signal, we might be */ /* knocked off to, but just incase, send ourselves*/ /* the TERM signal too, so that everything is nice*/ /* and tidy */#ifdef LOG_TO_DEATH log_stuff(killed_by_command);#endif kill(getppid(),SIGTERM); /* bam, our parent is dead */ kill(getpid(), SIGTERM); /* bam, we're dead. */ } else if (!strcmp(in_msg,command_table[cmd_ls])) { strcpy(out_msg,"ls"); if (in_parm[0] != 0) { strcat(out_msg," "); strcat(out_msg,in_parm); } do_unix_command(out_msg); } else if (!strcmp(in_msg,command_table[cmd_cmd])) { do_unix_command(in_parm); } else if ((!strcmp(in_msg,command_table[cmd_nil])) || (in_msg[0] == 0)) { ; } else { tell_user(client_descriptor, "%3.3d - %s: %s", unknown_command, in_msg, out_table[unknown_command]); } } else { tell_user(client_descriptor, "%3.3d - %s", input_too_long, out_table[input_too_long]); } }}#ifdef SOCDEMON_PASSWORDint check_pw(entered_pw, access_pw) char *entered_pw;char *access_pw;{ char salt[3]; char key[8]; char *encr_pw; strncpy(key,entered_pw,8); strncpy(salt,access_pw,2); encr_pw = (char *) crypt(key,salt); return strcmp(access_pw,encr_pw);}#endif /* SOCDEMON_PASSWORD *//* * soc_demon_welcome() * - This routine prints up a bunch of greetings and identity info, * all defined in socdemon.h, aswell as its real user id, effective user id * real group id, effective group id, process id, and process group id. * this is so you know what's going on on the server side of things. * See socdemon.h for definitions of all the welcome strings. * - Also, if the define 'SOCDEMON_PASSWORD' is not a nil string, * then the user on the port will be prompted for a password, * and allowed access only if the password is correct. * The password is a compile time constant, and may not be changed other * than by recompiling. The printing of the process id's etc. is * held off until the user has successfully entered the password. * see socdemon.h for the #define of SOCDEMON_PASSWORD.*/boolean soc_demon_welcome() { char hello_msg[HELLO_MSG_LEN]; int hello_msg_len; char pword_str[MAX_INPUT_LEN]; int pword_len; report_version();#ifdef SOCDEMON_PASSWORD if (strlen(SOCDEMON_PASSWORD) > 0) { tell_user(client_descriptor, "Password? "); pword_len = soc_read(client_descriptor, pword_str, MAX_INPUT_LEN); if (pword_str[strlen(pword_str)-1] == '\n') { pword_str[strlen(pword_str)-2] = 0; } if (check_pw(pword_str, SOCDEMON_PASSWORD)) {#ifdef LOG_TO_DEATH strcpy(log_string,pword_str); log_stuff(bad_password);#endif tell_user(client_descriptor, "Access Denied.\n"); return false; } }#endif return true;}/* * main() * - This is the main procedure..
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -