static void spoolss_setup_sig_hup_handler(struct tevent_context *ev_ctx, struct messaging_context *msg_ctx) { struct tevent_signal *se; se = tevent_add_signal(ev_ctx, ev_ctx, SIGHUP, 0, spoolss_sig_hup_handler, msg_ctx); if (!se) { exit_server("failed to setup SIGHUP handler"); } }
static bool blocking_lock_record_process(struct blocking_lock_record *blr) { switch(blr->req->cmd) { case SMBlockingX: return process_lockingX(blr); case SMBtrans2: case SMBtranss2: return process_trans2(blr); default: DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n")); exit_server("PANIC - unknown type on blocking lock queue"); } return False; /* Keep compiler happy. */ }
static void smbd_scavenger_parent_dead(struct tevent_context *event_ctx, struct tevent_fd *fde, uint16_t flags, void *private_data) { struct smbd_scavenger_state *state = talloc_get_type_abort( private_data, struct smbd_scavenger_state); struct server_id_buf tmp1, tmp2; DEBUG(2, ("scavenger: %s parent %s died\n", server_id_str_buf(*state->scavenger_id, &tmp1), server_id_str_buf(state->parent_id, &tmp2))); exit_server("smbd_scavenger_parent_dead"); }
static BOOL blocking_lock_record_process(blocking_lock_record *blr) { switch(blr->com_type) { case SMBlock: return process_lock(blr); case SMBlockread: return process_lockread(blr); case SMBlockingX: return process_lockingX(blr); default: DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n")); exit_server("PANIC - unknown type on blocking lock queue"); } return False; /* Keep compiler happy. */ }
bool dmapi_have_session(void) { if (!dmapi_ctx) { dmapi_ctx = talloc(NULL, struct smbd_dmapi_context); if (!dmapi_ctx) { exit_server("unable to allocate smbd_dmapi_context"); } dmapi_ctx->session = DM_NO_SESSION; dmapi_ctx->session_num = 0; become_root(); dmapi_init_session(dmapi_ctx); unbecome_root(); }
static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status) { switch(blr->com_type) { case SMBlock: case SMBlockread: generic_blocking_lock_error(blr, status); break; case SMBlockingX: reply_lockingX_error(blr, status); break; default: DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n")); exit_server("PANIC - unknown type on blocking lock queue"); } }
void smbd_init_globals(void) { set_smbd_shim(&smbd_shim_fns); ZERO_STRUCT(conn_ctx_stack); ZERO_STRUCT(sec_ctx_stack); smbd_server_conn = talloc_zero(server_event_context(), struct smbd_server_connection); if (!smbd_server_conn) { exit_server("failed to create smbd_server_connection"); } smbd_server_conn->smb1.echo_handler.trusted_fd = -1; smbd_server_conn->smb1.echo_handler.socket_lock_fd = -1; }
static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS status) { char *outbuf = OutBuffer; char *inbuf = blr->inbuf; construct_reply_common(inbuf, outbuf); /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to FILE_LOCK_CONFLICT! (tridge) */ if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) { status = NT_STATUS_FILE_LOCK_CONFLICT; } ERROR_NT(status); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("generic_blocking_lock_error: send_smb failed."); }
int main(int argc, char **argv) { static_assert(sizeof(pid_t) <= sizeof(long), "A POSIX-compliant implementation should have sizeof(pid_t) <= sizeof(long)"); if(argc != 4) usage(argv[0]); L = atoi(argv[1]); K = atoi(argv[2]); M = atoi(argv[3]); if(L < 0 || K < 0 || M < 0) usage(argv[0]); init(); run(); exit_server(0); }
static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status) { DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr)); switch(blr->req->cmd) { case SMBlockingX: /* * This code can be called during the rundown of a * file after it was already closed. In that case, * blr->fsp==NULL and we do not need to undo any * locks, they are already gone. */ if (blr->fsp != NULL) { undo_locks_obtained(blr); } generic_blocking_lock_error(blr, status); break; case SMBtrans2: case SMBtranss2: reply_nterror(blr->req, status); /* * construct_reply_common has done us the favor to pre-fill * the command field with SMBtranss2 which is wrong :-) */ SCVAL(blr->req->outbuf,smb_com,SMBtrans2); if (!srv_send_smb(blr->req->sconn, (char *)blr->req->outbuf, true, blr->req->seqnum+1, IS_CONN_ENCRYPTED(blr->fsp->conn), NULL)) { exit_server_cleanly("blocking_lock_reply_error: " "srv_send_smb failed."); } TALLOC_FREE(blr->req->outbuf); break; default: DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n")); exit_server("PANIC - unknown type on blocking lock queue"); } }
int main(int argc, char *argv[]) { L = atol(argv[1]); K = atol(argv[2]); M = atol(argv[3]); if (signal(SIGINT, exit_server) == SIG_ERR) syserr("Error in signal (SIGINT)"); init_queues(); int thr_err; pthread_t thread_id; make_attr_detached(); if (thr_err = pthread_rwlock_init(&rwlock, NULL)) syserr_ext(thr_err, "Error in function pthread_rwlock_init"); Mesg mesg; int bytes_rcvd; while (1) { if ((bytes_rcvd = msgrcv(msg_rcv_id, &mesg, MAX_BUFF, 0, 0)) <= 0) syserr("Error in msgrcv (receiving type(pid))"); mesg.mesg_data[bytes_rcvd] = '\0'; if (mesg.mesg_type == READ_TYPE_KOM) { if ((thr_err = pthread_create(&thread_id, &attr, serve_committee, &mesg.mesg_data)) != 0) syserr_ext(thr_err, "Error in pthread_create (for serve_committee)"); } else { if ((thr_err = pthread_create(&thread_id, &attr, serve_report, &mesg.mesg_data)) != 0) syserr_ext(thr_err, "Error in pthread_create (for serve_report)"); } } exit_server(0); }
/* initialise the mangling subsystem */ static void mangle_init(void) { int i; char *method; if (mangle_fns) return; method = lp_mangling_method(); /* find the first mangling method that manages to initialise and matches the "mangling method" parameter */ for (i=0; mangle_backends[i].name && !mangle_fns; i++) { if (!method || !*method || strcmp(method, mangle_backends[i].name) == 0) { mangle_fns = mangle_backends[i].init_fn(); } } if (!mangle_fns) { DEBUG(0,("Failed to initialise mangling system '%s'\n", method)); exit_server("mangling init failed"); } }
/** * Main function * Gareth application entry point * Initialise the database connection * Starts the webservice * Infinite loop until an end signal is triggered */ int main(int argc, char ** argv) { struct config_elements * config = malloc(sizeof(struct config_elements)); if (config == NULL) { fprintf(stderr, "Memory error - config\n"); return 1; } config->config_file = NULL; config->url_prefix = NULL; config->log_mode = Y_LOG_MODE_NONE; config->log_level = Y_LOG_LEVEL_NONE; config->log_file = NULL; config->conn = NULL; config->instance = malloc(sizeof(struct _u_instance)); if (config->instance == NULL) { fprintf(stderr, "Memory error - config->instance\n"); return 1; } ulfius_init_instance(config->instance, 1, NULL, NULL); global_handler_variable = GARETH_RUNNING; // Catch end signals to make a clean exit signal (SIGQUIT, exit_handler); signal (SIGINT, exit_handler); signal (SIGTERM, exit_handler); signal (SIGHUP, exit_handler); // First we parse command line arguments if (!build_config_from_args(argc, argv, config)) { fprintf(stderr, "Error reading command-line parameters\n"); print_help(stderr); exit_server(&config, GARETH_ERROR); } // Then we parse configuration file // They have lower priority than command line parameters if (!build_config_from_file(config)) { fprintf(stderr, "Error config file\n"); exit_server(&config, GARETH_ERROR); } // Check if all mandatory configuration variables are present and correctly typed if (!check_config(config)) { fprintf(stderr, "Error initializing configuration\n"); exit_server(&config, GARETH_ERROR); } // Initialize gareth webservice if (!init_gareth(config->instance, config->url_prefix, config->conn)) { fprintf(stderr, "Error initializing gareth webservice\n"); exit_server(&config, GARETH_ERROR); } // Default endpoint ulfius_set_default_endpoint(config->instance, &callback_default, (void*)config->conn); // Start the webservice y_log_message(Y_LOG_LEVEL_INFO, "Start gareth on port %d, prefix: %s", config->instance->port, config->url_prefix); if (ulfius_start_framework(config->instance) == U_OK) { while (global_handler_variable == GARETH_RUNNING) { sleep(1); } } else { y_log_message(Y_LOG_LEVEL_ERROR, "Error starting gareth webserver"); exit_server(&config, GARETH_ERROR); } exit_server(&config, GARETH_STOP); return 0; }
int main(int argc,const char *argv[]) { /* shall I run as a daemon */ bool is_daemon = false; bool interactive = false; bool Fork = true; bool no_process_group = false; bool log_stdout = false; char *ports = NULL; char *profile_level = NULL; int opt; poptContext pc; bool print_build_options = False; enum { OPT_DAEMON = 1000, OPT_INTERACTIVE, OPT_FORK, OPT_NO_PROCESS_GROUP, OPT_LOG_STDOUT }; struct poptOption long_options[] = { POPT_AUTOHELP {"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" }, {"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE, "Run interactive (not a daemon)"}, {"foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Run daemon in foreground (for daemontools, etc.)" }, {"no-process-group", '\0', POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" }, {"log-stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" }, {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, {"profiling-level", 'P', POPT_ARG_STRING, &profile_level, 0, "Set profiling level","PROFILE_LEVEL"}, POPT_COMMON_SAMBA POPT_COMMON_DYNCONFIG POPT_TABLEEND }; struct smbd_parent_context *parent = NULL; TALLOC_CTX *frame; NTSTATUS status; uint64_t unique_id; struct tevent_context *ev_ctx; struct messaging_context *msg_ctx; /* * Do this before any other talloc operation */ talloc_enable_null_tracking(); frame = talloc_stackframe(); setup_logging(argv[0], DEBUG_DEFAULT_STDOUT); load_case_tables(); smbd_init_globals(); TimeInit(); #ifdef HAVE_SET_AUTH_PARAMETERS set_auth_parameters(argc,argv); #endif pc = poptGetContext("smbd", argc, argv, long_options, 0); while((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_DAEMON: is_daemon = true; break; case OPT_INTERACTIVE: interactive = true; break; case OPT_FORK: Fork = false; break; case OPT_NO_PROCESS_GROUP: no_process_group = true; break; case OPT_LOG_STDOUT: log_stdout = true; break; case 'b': print_build_options = True; break; default: d_fprintf(stderr, "\nInvalid option %s: %s\n\n", poptBadOption(pc, 0), poptStrerror(opt)); poptPrintUsage(pc, stderr, 0); exit(1); } } poptFreeContext(pc); if (interactive) { Fork = False; log_stdout = True; } if (log_stdout) { setup_logging(argv[0], DEBUG_STDOUT); } else { setup_logging(argv[0], DEBUG_FILE); } if (print_build_options) { build_options(True); /* Display output to screen as well as debug */ exit(0); } #ifdef HAVE_SETLUID /* needed for SecureWare on SCO */ setluid(0); #endif set_remote_machine_name("smbd", False); if (interactive && (DEBUGLEVEL >= 9)) { talloc_enable_leak_report(); } if (log_stdout && Fork) { DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); exit(1); } /* we want to re-seed early to prevent time delays causing client problems at a later date. (tridge) */ generate_random_buffer(NULL, 0); /* get initial effective uid and gid */ sec_init(); /* make absolutely sure we run as root - to handle cases where people are crazy enough to have it setuid */ gain_root_privilege(); gain_root_group_privilege(); fault_setup(); dump_core_setup("smbd", lp_logfile()); /* we are never interested in SIGPIPE */ BlockSignals(True,SIGPIPE); #if defined(SIGFPE) /* we are never interested in SIGFPE */ BlockSignals(True,SIGFPE); #endif #if defined(SIGUSR2) /* We are no longer interested in USR2 */ BlockSignals(True,SIGUSR2); #endif /* POSIX demands that signals are inherited. If the invoking process has * these signals masked, we will have problems, as we won't recieve them. */ BlockSignals(False, SIGHUP); BlockSignals(False, SIGUSR1); BlockSignals(False, SIGTERM); /* Ensure we leave no zombies until we * correctly set up child handling below. */ CatchChild(); /* we want total control over the permissions on created files, so set our umask to 0 */ umask(0); reopen_logs(); DEBUG(0,("smbd version %s started.\n", samba_version_string())); DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE)); DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); /* Output the build options to the debug log */ build_options(False); if (sizeof(uint16) < 2 || sizeof(uint32) < 4) { DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n")); exit(1); } if (!lp_load_initial_only(get_dyn_CONFIGFILE())) { DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE())); exit(1); } /* Init the security context and global current_user */ init_sec_ctx(); /* * Initialize the event context. The event context needs to be * initialized before the messaging context, cause the messaging * context holds an event context. * FIXME: This should be s3_tevent_context_init() */ ev_ctx = server_event_context(); if (ev_ctx == NULL) { exit(1); } /* * Init the messaging context * FIXME: This should only call messaging_init() */ msg_ctx = server_messaging_context(); if (msg_ctx == NULL) { exit(1); } /* * Reloading of the printers will not work here as we don't have a * server info and rpc services set up. It will be called later. */ if (!reload_services(NULL, -1, False)) { exit(1); } /* ...NOTE... Log files are working from this point! */ DEBUG(3,("loaded services\n")); init_structs(); #ifdef WITH_PROFILE if (!profile_setup(msg_ctx, False)) { DEBUG(0,("ERROR: failed to setup profiling\n")); return -1; } if (profile_level != NULL) { int pl = atoi(profile_level); struct server_id src; DEBUG(1, ("setting profiling level: %s\n",profile_level)); src.pid = getpid(); set_profile_level(pl, src); } #endif if (!is_daemon && !is_a_socket(0)) { if (!interactive) DEBUG(0,("standard input is not a socket, assuming -D option\n")); /* * Setting is_daemon here prevents us from eventually calling * the open_sockets_inetd() */ is_daemon = True; } if (is_daemon && !interactive) { DEBUG( 3, ( "Becoming a daemon.\n" ) ); become_daemon(Fork, no_process_group, log_stdout); } generate_random_buffer((uint8_t *)&unique_id, sizeof(unique_id)); set_my_unique_id(unique_id); #if HAVE_SETPGID /* * If we're interactive we want to set our own process group for * signal management. */ if (interactive && !no_process_group) setpgid( (pid_t)0, (pid_t)0); #endif if (!directory_exist(lp_lockdir())) mkdir(lp_lockdir(), 0755); if (is_daemon) pidfile_create("smbd"); status = reinit_after_fork(msg_ctx, ev_ctx, procid_self(), false); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); exit(1); } smbd_server_conn->msg_ctx = msg_ctx; smbd_setup_sig_term_handler(); smbd_setup_sig_hup_handler(ev_ctx, msg_ctx); /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ if (smbd_memcache() == NULL) { exit(1); } memcache_set_global(smbd_memcache()); /* Initialise the password backed before the global_sam_sid to ensure that we fetch from ldap before we make a domain sid up */ if(!initialize_password_db(false, ev_ctx)) exit(1); if (!secrets_init()) { DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n")); exit(1); } if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) { struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_context()); if (!open_schannel_session_store(NULL, lp_ctx)) { DEBUG(0,("ERROR: Samba cannot open schannel store for secured NETLOGON operations.\n")); exit(1); } TALLOC_FREE(lp_ctx); } if(!get_global_sam_sid()) { DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); exit(1); } if (!sessionid_init()) { exit(1); } if (!connections_init(True)) exit(1); if (!locking_init()) exit(1); if (!messaging_tdb_parent_init(ev_ctx)) { exit(1); } if (!notify_internal_parent_init(ev_ctx)) { exit(1); } if (!serverid_parent_init(ev_ctx)) { exit(1); } if (!W_ERROR_IS_OK(registry_init_full())) exit(1); /* Open the share_info.tdb here, so we don't have to open after the fork on every single connection. This is a small performance improvment and reduces the total number of system fds used. */ if (!share_info_db_init()) { DEBUG(0,("ERROR: failed to load share info db.\n")); exit(1); } status = init_system_info(); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("ERROR: failed to setup system user info: %s.\n", nt_errstr(status))); return -1; } if (!init_guest_info()) { DEBUG(0,("ERROR: failed to setup guest info.\n")); return -1; } if (!file_init(smbd_server_conn)) { DEBUG(0, ("ERROR: file_init failed\n")); return -1; } /* This MUST be done before start_epmd() because otherwise * start_epmd() forks and races against dcesrv_ep_setup() to * call directory_create_or_exist() */ if (!directory_create_or_exist(lp_ncalrpc_dir(), geteuid(), 0755)) { DEBUG(0, ("Failed to create pipe directory %s - %s\n", lp_ncalrpc_dir(), strerror(errno))); return -1; } if (is_daemon && !interactive) { if (rpc_epmapper_daemon() == RPC_DAEMON_FORK) { start_epmd(ev_ctx, msg_ctx); } } if (!dcesrv_ep_setup(ev_ctx, msg_ctx)) { exit(1); } /* only start other daemons if we are running as a daemon * -- bad things will happen if smbd is launched via inetd * and we fork a copy of ourselves here */ if (is_daemon && !interactive) { if (rpc_lsasd_daemon() == RPC_DAEMON_FORK) { start_lsasd(ev_ctx, msg_ctx); } if (!_lp_disable_spoolss() && (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) { bool bgq = lp_parm_bool(-1, "smbd", "backgroundqueue", true); if (!printing_subsystem_init(ev_ctx, msg_ctx, true, bgq)) { exit(1); } } } else if (!_lp_disable_spoolss() && (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) { if (!printing_subsystem_init(ev_ctx, msg_ctx, false, false)) { exit(1); } } if (!is_daemon) { /* inetd mode */ TALLOC_FREE(frame); /* Started from inetd. fd 0 is the socket. */ /* We will abort gracefully when the client or remote system goes away */ smbd_server_conn->sock = dup(0); /* close our standard file descriptors */ if (!debug_get_output_is_stdout()) { close_low_fds(False); /* Don't close stderr */ } #ifdef HAVE_ATEXIT atexit(killkids); #endif /* Stop zombies */ smbd_setup_sig_chld_handler(ev_ctx); smbd_process(ev_ctx, smbd_server_conn); exit_server_cleanly(NULL); return(0); } parent = talloc_zero(ev_ctx, struct smbd_parent_context); if (!parent) { exit_server("talloc(struct smbd_parent_context) failed"); } parent->interactive = interactive; if (!open_sockets_smbd(parent, ev_ctx, msg_ctx, ports)) exit_server("open_sockets_smbd() failed"); /* do a printer update now that all messaging has been set up, * before we allow clients to start connecting */ printing_subsystem_update(ev_ctx, msg_ctx, false); TALLOC_FREE(frame); /* make sure we always have a valid stackframe */ frame = talloc_stackframe(); smbd_parent_loop(ev_ctx, parent); exit_server_cleanly(NULL); TALLOC_FREE(frame); return(0); }
int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, int length,int bufsize) { int sess_vuid; int smb_bufsize; DATA_BLOB lm_resp; DATA_BLOB nt_resp; DATA_BLOB plaintext_password; fstring user; fstring sub_user; /* Sainitised username for substituion */ fstring domain; fstring native_os; fstring native_lanman; fstring primary_domain; static BOOL done_sesssetup = False; extern BOOL global_encrypted_passwords_negotiated; extern BOOL global_spnego_negotiated; extern enum protocol_types Protocol; extern int max_send; auth_usersupplied_info *user_info = NULL; extern struct auth_context *negprot_global_auth_context; auth_serversupplied_info *server_info = NULL; NTSTATUS nt_status; BOOL doencrypt = global_encrypted_passwords_negotiated; DATA_BLOB session_key; START_PROFILE(SMBsesssetupX); ZERO_STRUCT(lm_resp); ZERO_STRUCT(nt_resp); ZERO_STRUCT(plaintext_password); DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2))); /* a SPNEGO session setup has 12 command words, whereas a normal NT1 session setup has 13. See the cifs spec. */ if (CVAL(inbuf, smb_wct) == 12 && (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { if (!global_spnego_negotiated) { DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n")); return ERROR_NT(NT_STATUS_UNSUCCESSFUL); } if (SVAL(inbuf,smb_vwv4) == 0) { setup_new_vc_session(); } return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize); } smb_bufsize = SVAL(inbuf,smb_vwv2); if (Protocol < PROTOCOL_NT1) { uint16 passlen1 = SVAL(inbuf,smb_vwv7); if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } if (doencrypt) { lm_resp = data_blob(smb_buf(inbuf), passlen1); } else { plaintext_password = data_blob(smb_buf(inbuf), passlen1+1); /* Ensure null termination */ plaintext_password.data[passlen1] = 0; } srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE); *domain = 0; } else { uint16 passlen1 = SVAL(inbuf,smb_vwv7); uint16 passlen2 = SVAL(inbuf,smb_vwv8); enum remote_arch_types ra_type = get_remote_arch(); char *p = smb_buf(inbuf); char *save_p = smb_buf(inbuf); uint16 byte_count; if(global_client_caps == 0) { global_client_caps = IVAL(inbuf,smb_vwv11); if (!(global_client_caps & CAP_STATUS32)) { remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); } /* client_caps is used as final determination if client is NT or Win95. This is needed to return the correct error codes in some circumstances. */ if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) { if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) { set_remote_arch( RA_WIN95); } } } if (!doencrypt) { /* both Win95 and WinNT stuff up the password lengths for non-encrypting systems. Uggh. if passlen1==24 its a win95 system, and its setting the password length incorrectly. Luckily it still works with the default code because Win95 will null terminate the password anyway if passlen1>0 and passlen2>0 then maybe its a NT box and its setting passlen2 to some random value which really stuffs things up. we need to fix that one. */ if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1) passlen2 = 0; } /* check for nasty tricks */ if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) { return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } /* Save the lanman2 password and the NT md4 password. */ if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) { doencrypt = False; } if (doencrypt) { lm_resp = data_blob(p, passlen1); nt_resp = data_blob(p+passlen1, passlen2); } else { pstring pass; BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS; #if 0 /* This was the previous fix. Not sure if it's still valid. JRA. */ if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) { /* NT4.0 stuffs up plaintext unicode password lengths... */ srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1, sizeof(pass), passlen1, STR_TERMINATE); #endif if (unic && (passlen2 == 0) && passlen1) { /* Only a ascii plaintext password was sent. */ srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass), passlen1, STR_TERMINATE|STR_ASCII); } else { srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass), unic ? passlen2 : passlen1, STR_TERMINATE); } plaintext_password = data_blob(pass, strlen(pass)+1); } p += passlen1 + passlen2; p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE); p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE); p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE); p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE); /* not documented or decoded by Ethereal but there is one more string in the extra bytes which is the same as the PrimaryDomain when using extended security. Windows NT 4 and 2003 use this string to store the native lanman string. Windows 9x does not include a string here at all so we have to check if we have any extra bytes left */ byte_count = SVAL(inbuf, smb_vwv13); if ( PTR_DIFF(p, save_p) < byte_count) p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE); else fstrcpy( primary_domain, "null" ); DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", domain, native_os, native_lanman, primary_domain)); if ( ra_type == RA_WIN2K ) { if ( strlen(native_lanman) == 0 ) ra_lanman_string( primary_domain ); else ra_lanman_string( native_lanman ); } } if (SVAL(inbuf,smb_vwv4) == 0) { setup_new_vc_session(); } DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name())); if (*user) { if (global_spnego_negotiated) { /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */ DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); return ERROR_NT(NT_STATUS_UNSUCCESSFUL); } fstrcpy(sub_user, user); /* setup the string used by %U */ sub_set_smb_name(user); } else { fstrcpy(sub_user, lp_guestaccount()); } sub_set_smb_name(sub_user); reload_services(True); if (lp_security() == SEC_SHARE) { /* in share level we should ignore any passwords */ data_blob_free(&lm_resp); data_blob_free(&nt_resp); data_blob_clear_free(&plaintext_password); map_username(sub_user); add_session_user(sub_user); /* Then force it to null for the benfit of the code below */ *user = 0; } if (!*user) { nt_status = check_guest_password(&server_info); } else if (doencrypt) { if (!negprot_global_auth_context) { DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n")); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } nt_status = make_user_info_for_reply_enc(&user_info, user, domain, lm_resp, nt_resp); if (NT_STATUS_IS_OK(nt_status)) { nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, user_info, &server_info); } } else { struct auth_context *plaintext_auth_context = NULL; const uint8 *chal; if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) { chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context); if (!make_user_info_for_reply(&user_info, user, domain, chal, plaintext_password)) { nt_status = NT_STATUS_NO_MEMORY; } if (NT_STATUS_IS_OK(nt_status)) { nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, user_info, &server_info); (plaintext_auth_context->free)(&plaintext_auth_context); } } } free_user_info(&user_info); if (!NT_STATUS_IS_OK(nt_status)) { nt_status = do_map_to_guest(nt_status, &server_info, user, domain); } if (!NT_STATUS_IS_OK(nt_status)) { data_blob_free(&nt_resp); data_blob_free(&lm_resp); data_blob_clear_free(&plaintext_password); return ERROR_NT(nt_status_squash(nt_status)); } if (server_info->user_session_key.data) { session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length); } else { session_key = data_blob(NULL, 0); } data_blob_clear_free(&plaintext_password); /* it's ok - setup a reply */ set_message(outbuf,3,0,True); if (Protocol >= PROTOCOL_NT1) { char *p = smb_buf( outbuf ); p += add_signature( outbuf, p ); set_message_end( outbuf, p ); /* perhaps grab OS version here?? */ } if (server_info->guest) { SSVAL(outbuf,smb_vwv2,1); } /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ /* register_vuid keeps the server info */ sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user); data_blob_free(&nt_resp); data_blob_free(&lm_resp); if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } /* current_user_info is changed on new vuid */ reload_services( True ); if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) { exit_server("reply_sesssetup_and_X: bad smb signature"); } SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); if (!done_sesssetup) max_send = MIN(max_send,smb_bufsize); done_sesssetup = True; END_PROFILE(SMBsesssetupX); return chain_reply(inbuf,outbuf,length,bufsize); }
static bool smbd_scavenger_start(struct smbd_scavenger_state *state) { struct server_id self = messaging_server_id(state->msg); struct tevent_fd *fde = NULL; int fds[2]; int ret; uint64_t unique_id; bool ok; SMB_ASSERT(server_id_equal(&state->parent_id, &self)); if (smbd_scavenger_running(state)) { DEBUG(10, ("scavenger %s already running\n", server_id_str(talloc_tos(), state->scavenger_id))); return true; } if (state->scavenger_id != NULL) { DEBUG(10, ("scavenger zombie %s, cleaning up\n", server_id_str(talloc_tos(), state->scavenger_id))); TALLOC_FREE(state->scavenger_id); } state->scavenger_id = talloc_zero(state, struct server_id); if (state->scavenger_id == NULL) { DEBUG(2, ("Out of memory\n")); goto fail; } talloc_set_destructor(state->scavenger_id, smbd_scavenger_server_id_destructor); ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); if (ret == -1) { DEBUG(2, ("socketpair failed: %s", strerror(errno))); goto fail; } smb_set_close_on_exec(fds[0]); smb_set_close_on_exec(fds[1]); unique_id = serverid_get_random_unique_id(); ret = fork(); if (ret == -1) { int err = errno; close(fds[0]); close(fds[1]); DEBUG(0, ("fork failed: %s", strerror(err))); goto fail; } if (ret == 0) { /* child */ NTSTATUS status; close(fds[0]); am_parent = NULL; set_my_unique_id(unique_id); status = reinit_after_fork(state->msg, state->ev, true); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("reinit_after_fork failed: %s\n", nt_errstr(status))); exit_server("reinit_after_fork failed"); return false; } prctl_set_comment("smbd-scavenger"); state->am_scavenger = true; *state->scavenger_id = messaging_server_id(state->msg); scavenger_setup_sig_term_handler(state->ev); serverid_register(*state->scavenger_id, FLAG_MSG_GENERAL); ok = scavenger_say_hello(fds[1], *state->scavenger_id); if (!ok) { DEBUG(2, ("scavenger_say_hello failed\n")); exit_server("scavenger_say_hello failed"); return false; } fde = tevent_add_fd(state->ev, state->scavenger_id, fds[1], TEVENT_FD_READ, smbd_scavenger_parent_dead, state); if (fde == NULL) { DEBUG(2, ("tevent_add_fd(smbd_scavenger_parent_dead) " "failed\n")); exit_server("tevent_add_fd(smbd_scavenger_parent_dead) " "failed"); return false; } tevent_fd_set_auto_close(fde); ret = smbd_scavenger_main(state); DEBUG(10, ("scavenger ended: %d\n", ret)); exit_server_cleanly("scavenger ended"); return false; } /* parent */ close(fds[1]); ok = scavenger_wait_hello(fds[0], state->scavenger_id); if (!ok) { close(fds[0]); goto fail; } fde = tevent_add_fd(state->ev, state->scavenger_id, fds[0], TEVENT_FD_READ, smbd_scavenger_done, state); if (fde == NULL) { close(fds[0]); goto fail; } tevent_fd_set_auto_close(fde); return true; fail: TALLOC_FREE(state->scavenger_id); return false; }
int reply_negprot(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) { int outsize = set_message(outbuf,1,0,True); int Index=0; int choice= -1; int protocol; char *p; int bcc = SVAL(smb_buf(inbuf),-2); int arch = ARCH_ALL; static BOOL done_negprot = False; START_PROFILE(SMBnegprot); if (done_negprot) { END_PROFILE(SMBnegprot); exit_server("multiple negprot's are not permitted"); } done_negprot = True; p = smb_buf(inbuf)+1; while (p < (smb_buf(inbuf) + bcc)) { Index++; DEBUG(3,("Requested protocol [%s]\n",p)); if (strcsequal(p,"Windows for Workgroups 3.1a")) arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K ); else if (strcsequal(p,"DOS LM1.2X002")) arch &= ( ARCH_WFWG | ARCH_WIN95 ); else if (strcsequal(p,"DOS LANMAN2.1")) arch &= ( ARCH_WFWG | ARCH_WIN95 ); else if (strcsequal(p,"NT LM 0.12")) arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS); else if (strcsequal(p,"LANMAN2.1")) arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 ); else if (strcsequal(p,"LM1.2X002")) arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 ); else if (strcsequal(p,"MICROSOFT NETWORKS 1.03")) arch &= ARCH_WINNT; else if (strcsequal(p,"XENIX CORE")) arch &= ( ARCH_WINNT | ARCH_OS2 ); else if (strcsequal(p,"Samba")) { arch = ARCH_SAMBA; break; } else if (strcsequal(p,"POSIX 2")) { arch = ARCH_CIFSFS; break; } p += strlen(p) + 2; } /* CIFSFS can send one arch only, NT LM 0.12. */ if (Index == 1 && (arch & ARCH_CIFSFS)) { arch = ARCH_CIFSFS; } switch ( arch ) { case ARCH_CIFSFS: set_remote_arch(RA_CIFSFS); break; case ARCH_SAMBA: set_remote_arch(RA_SAMBA); break; case ARCH_WFWG: set_remote_arch(RA_WFWG); break; case ARCH_WIN95: set_remote_arch(RA_WIN95); break; case ARCH_WINNT: if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE) set_remote_arch(RA_WIN2K); else set_remote_arch(RA_WINNT); break; case ARCH_WIN2K: set_remote_arch(RA_WIN2K); break; case ARCH_OS2: set_remote_arch(RA_OS2); break; default: set_remote_arch(RA_UNKNOWN); break; } /* possibly reload - change of architecture */ reload_services(True); /* moved from the netbios session setup code since we don't have that when the client connects to port 445. Of course there is a small window where we are listening to messages -- jerry */ claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL); /* Check for protocols, most desirable first */ for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) { p = smb_buf(inbuf)+1; Index = 0; if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) && (supported_protocols[protocol].protocol_level >= lp_minprotocol())) while (p < (smb_buf(inbuf) + bcc)) { if (strequal(p,supported_protocols[protocol].proto_name)) choice = Index; Index++; p += strlen(p) + 2; } if(choice != -1) break; } SSVAL(outbuf,smb_vwv0,choice); if(choice != -1) { extern fstring remote_proto; fstrcpy(remote_proto,supported_protocols[protocol].short_name); reload_services(True); outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf); DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); } else { DEBUG(0,("No protocol supported !\n")); } SSVAL(outbuf,smb_vwv0,choice); DEBUG( 5, ( "negprot index=%d\n", choice ) ); if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) { exit_server("SMB signing is required and client negotiated a downlevel protocol"); } END_PROFILE(SMBnegprot); return(outsize); }
int main(int argc, char *argv[]) #endif { fd_set rfds; struct timeval tv; int server_socket = -1; int bytes, retval; struct dhcpMessage packet; unsigned char *state; unsigned char *server_id, *requested, *hostname; u_int32_t server_id_align, requested_align; unsigned long timeout_end; struct option_set *option; struct dhcpOfferedAddr *lease; int pid_fd; int max_sock; int sig; OPEN_LOG("udhcpd"); LOG(LOG_INFO, "udhcp server (v%s) started", VERSION); memset(&server_config, 0, sizeof(struct server_config_t)); if (argc < 2) read_config(DHCPD_CONF_FILE); else read_config(argv[1]); pid_fd = pidfile_acquire(server_config.pidfile); pidfile_write_release(pid_fd); if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) { memcpy(&server_config.lease, option->data + 2, 4); server_config.lease = ntohl(server_config.lease); } else server_config.lease = LEASE_TIME; leases = malloc(sizeof(struct dhcpOfferedAddr) * server_config.max_leases); memset(leases, 0, sizeof(struct dhcpOfferedAddr) * server_config.max_leases); // Added by Joey to load static lease if (argc>=3) { load_leases(argv[2]); } read_leases(server_config.lease_file); if (read_interface(server_config.interface, &server_config.ifindex, &server_config.server, server_config.arp) < 0) exit_server(1); #ifndef DEBUGGING pid_fd = pidfile_acquire(server_config.pidfile); /* hold lock during fork. */ if (daemon(0, 0) == -1) { perror("fork"); exit_server(1); } pidfile_write_release(pid_fd); #endif /* ensure that stdin/stdout/stderr are never returned by pipe() */ if (fcntl(STDIN_FILENO, F_GETFL) == -1) (void) open("/dev/null", O_RDONLY); if (fcntl(STDOUT_FILENO, F_GETFL) == -1) (void) open("/dev/null", O_WRONLY); if (fcntl(STDERR_FILENO, F_GETFL) == -1) (void) open("/dev/null", O_WRONLY); /* setup signal handlers */ pipe(signal_pipe); signal(SIGUSR1, signal_handler); signal(SIGTERM, signal_handler); timeout_end = uptime() + server_config.auto_time; while(1) { /* loop until universe collapses */ if (server_socket < 0) if ((server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface)) < 0) { LOG(LOG_ERR, "FATAL: couldn't create server socket, %s", strerror(errno)); exit_server(0); } FD_ZERO(&rfds); FD_SET(server_socket, &rfds); FD_SET(signal_pipe[0], &rfds); if (server_config.auto_time) { tv.tv_sec = timeout_end - uptime(); tv.tv_usec = 0; } if (!server_config.auto_time || tv.tv_sec > 0) { max_sock = server_socket > signal_pipe[0] ? server_socket : signal_pipe[0]; retval = select(max_sock + 1, &rfds, NULL, NULL, server_config.auto_time ? &tv : NULL); } else retval = 0; /* If we already timed out, fall through */ if (retval == 0) { write_leases(); timeout_end = uptime() + server_config.auto_time; continue; } else if (retval < 0 && errno != EINTR) { DEBUG(LOG_INFO, "error on select"); continue; } if (FD_ISSET(signal_pipe[0], &rfds)) { if (read(signal_pipe[0], &sig, sizeof(sig)) < 0) continue; /* probably just EINTR */ switch (sig) { case SIGUSR1: LOG(LOG_INFO, "Received a SIGUSR1"); write_leases(); /* why not just reset the timeout, eh */ timeout_end = uptime() + server_config.auto_time; continue; case SIGTERM: LOG(LOG_INFO, "Received a SIGTERM"); exit_server(0); } } if ((bytes = get_packet(&packet, server_socket)) < 0) { /* this waits for a packet - idle */ if (bytes == -1 && errno != EINTR) { DEBUG(LOG_INFO, "error on read, %s, reopening socket", strerror(errno)); close(server_socket); server_socket = -1; } continue; } if ((state = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { DEBUG(LOG_ERR, "couldn't get option from packet, ignoring"); continue; } server_id = get_option(&packet, DHCP_SERVER_ID); if (server_id) { memcpy(&server_id_align, server_id, 4); if (server_id_align != server_config.server) { /* client talks to somebody else */ DEBUG(LOG_INFO,"server ID %08x doesn't match, ignoring", ntohl(server_id_align)); continue; } } /* ADDME: look for a static lease */ lease = find_lease_by_chaddr(packet.chaddr); switch (state[0]) { case DHCPDISCOVER: DEBUG(LOG_INFO,"received DISCOVER"); if (sendOffer(&packet) < 0) { LOG(LOG_ERR, "send OFFER failed"); } break; case DHCPREQUEST: DEBUG(LOG_INFO, "received REQUEST"); requested = get_option(&packet, DHCP_REQUESTED_IP); hostname = get_option(&packet, DHCP_HOST_NAME); if (requested) memcpy(&requested_align, requested, 4); if (lease) { /*ADDME: or static lease */ if (server_id) { /* SELECTING State */ if (requested && requested_align == lease->yiaddr) { sendACK(&packet, lease->yiaddr); } } else { if (requested) { /* INIT-REBOOT State */ if (lease->yiaddr == requested_align) sendACK(&packet, lease->yiaddr); else sendNAK(&packet); } else { /* RENEWING or REBINDING State */ if (lease->yiaddr == packet.ciaddr) sendACK(&packet, lease->yiaddr); else { /* don't know what to do!!!! */ sendNAK(&packet); } } } if (hostname) { bytes = hostname[-1]; if (bytes >= (int) sizeof(lease->hostname)) bytes = sizeof(lease->hostname) - 1; strncpy(lease->hostname, hostname, bytes); lease->hostname[bytes] = '\0'; if (!is_valid_hostname(lease->hostname)) lease->hostname[0] = '\0'; } else lease->hostname[0] = '\0'; /* what to do if we have no record of the client */ } else if (server_id) { /* SELECTING State */ if (requested) sendNAK(&packet); } else if (requested) { /* INIT-REBOOT State */ if ((lease = find_lease_by_yiaddr(requested_align))) { if (lease_expired(lease)) { /* probably best if we drop this lease */ memset(lease->chaddr, 0, 16); /* make some contention for this address */ } else sendNAK(&packet); } else if (requested_align < server_config.start || requested_align > server_config.end) { sendNAK(&packet); } else { sendNAK(&packet); } } else if (packet.ciaddr) { /* RENEWING or REBINDING State */ sendNAK(&packet); } break; case DHCPDECLINE: DEBUG(LOG_INFO,"received DECLINE"); if (lease) { memset(lease->chaddr, 0, 16); lease->expires = uptime() + server_config.decline_time; } break; case DHCPRELEASE: DEBUG(LOG_INFO,"received RELEASE"); if (lease) lease->expires = uptime(); break; case DHCPINFORM: DEBUG(LOG_INFO,"received INFORM"); send_inform(&packet); break; default: LOG(LOG_WARNING, "unsupported DHCP message (%02x) -- ignoring", state[0]); } } return 0; }
void exit_server_fault(void) { exit_server("critical server fault"); }
_Noreturn void signal_handler() { // If the server is commiting suicide (i.e. an error has occurred) // interrupted == true BEFORE entering the signal handler, so the // exit code will be set accordingly exit_server(interrupted); }
int listen_for_connections(void) { struct sockaddr_in serveraddr, clientaddr; int request_sd; int numsocks = 0; int maxsocks = 10; int sock[maxsocks]; int receive; int clientaddrlen = sizeof(struct sockaddr); fd_set readfds, fds; struct timeval time; time.tv_sec = 20; time.tv_usec = 0; //request-socket, lytter på innkommende forbindelser request_sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //adresse struct memset((void*) &serveraddr, 0, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = INADDR_ANY; if(listening_port != 0) { serveraddr.sin_port = htons(listening_port); printf("Listening for connections on port '%d'\n", listening_port); } else { serveraddr.sin_port = htons(9090); //default if no port is provided printf("Listening for connections on default port '9090'\n"); } //bind adressen til socketen bind(request_sd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)); //start lytting listen(request_sd, SOMAXCONN); FD_ZERO(&readfds); FD_ZERO(&fds); FD_SET(request_sd, &fds); FD_SET(0, &fds); numsocks++; for(;;) { readfds = fds; receive = select(maxsocks + 1, &readfds, NULL, NULL, &time); if(receive < 0) { perror("select encountered an error.\n"); return -1; } else if(receive == 0) { //timeout, do nothing } else { int i; for(i = 0; i < FD_SETSIZE; i++) { if(FD_ISSET(i, &readfds)) { if(i == 0) { //stdin look for ctrl-d if(read(i, NULL, 10) == 0) { for(i = 0; i < numsocks; i++) { close(sock[i]); FD_CLR(sock[i], &fds); } exit_server(); } } if(i == request_sd) { if(numsocks < maxsocks) { sock[numsocks] = accept(request_sd, (struct sockaddr *) &clientaddr, (socklen_t *) &clientaddrlen); FD_SET(sock[numsocks], &fds); numsocks++; } else { //No more space for sockets perror("Ran out of socket space.\n"); for(i = 0; i < numsocks; i++) { close(sock[i]); FD_CLR(sock[i], &fds); } exit_server(); } } else { //read first 4 bytes, and determine what kind of package is coming char buf[4]; memset(buf, 0, 4); if(read(i, buf, 4) == -1) { perror("Error reading from client.\n"); return -1; } int size = bytes_to_int(buf); byte msg_type = buf[2]; if(msg_type == SCORE_LIST) { int score_packages = btotci(buf[3]); if(score_packages > 0) { score *scores[score_packages]; int count; for(count = 0; count < score_packages; count++) { scores[count] = init_score(); } int result = receive_score(i, score_packages, scores); if(result != -1) { for(count = 0; count < score_packages; count++) { add_score(scores[count]); } } for(count = 0; count < score_packages; count++) { free(scores[count]); } } else if(score_packages < 0) { //reply with abs(score_packages); int num = abs(score_packages); score *s[num]; int count; count = get_scores(num, s); if(send_score_list(i, s, count) < 0) { perror("Closing connection.\n"); close(i); FD_CLR(i, &fds); } } } else if(msg_type == SHUTDOWN_NOTIFICATION) { //receive shutdown msg char buf[size - 4]; //First 4 bytes allready read. int result = receive_shutdown_notification(i, buf, size - 4); if(result == 0) { printf("Received shutdown notification: %s\n", buf); close(i); FD_CLR(i, &fds); } } else { //error, unknown type, reply with shutdown notification perror("Sending shutdown_notification.\n"); send_shutdown_notification(i, "Unknown msg_type, got: " + msg_type); //close and remove socket criptor close(i); FD_CLR(i, &fds); } } } } } } int i; for(i = 0; i < maxsocks; i++) { close(sock[i]); } close(request_sd); return 0; }
/* ** exit_client ** This is old "m_bye". Name changed, because this is not a ** protocol function, but a general server utility function. ** ** This function exits a client of *any* type (user, server, etc) ** from this server. Also, this generates all necessary prototol ** messages that this exit may cause. ** ** 1) If the client is a local client, then this implicitly ** exits all other clients depending on this connection (e.g. ** remote clients having 'from'-field that points to this. ** ** 2) If the client is a remote client, then only this is exited. ** ** For convenience, this function returns a suitable value for ** m_funtion return value: ** ** FLUSH_BUFFER if (cptr == sptr) ** 0 if (cptr != sptr) ** ** Parameters: ** ** aClient *cptr ** The local client originating the exit or NULL, if this ** exit is generated by this server for internal reasons. ** This will not get any of the generated messages. ** aClient *sptr ** Client exiting ** aClient *from ** Client firing off this Exit, never NULL! ** char *comment ** Reason for the exit */ int exit_client(aClient *cptr, aClient *sptr, aClient *from, const char *comment) { char comment1[HOSTLEN + HOSTLEN + 2]; if (MyConnect(sptr)) { if (sptr->flags & FLAGS_KILLED) { sendto_flag(SCH_NOTICE, "Killed: %s.", get_client_name(sptr, TRUE)); sptr->exitc = EXITC_KILL; } sptr->flags |= FLAGS_CLOSING; #if (defined(FNAME_USERLOG) || defined(FNAME_CONNLOG) \ || defined(USE_SERVICES)) \ || (defined(USE_SYSLOG) && (defined(SYSLOG_USERS) || defined(SYSLOG_CONN))) if (IsPerson(sptr)) { # if defined(FNAME_USERLOG) || defined(USE_SERVICES) || \ (defined(USE_SYSLOG) && defined(SYSLOG_USERS)) sendto_flog(sptr, EXITC_REG, sptr->user->username, sptr->user->host); # endif # if defined(CLIENTS_CHANNEL) && (CLIENTS_CHANNEL_LEVEL & CCL_QUIT) sendto_flag(SCH_CLIENT, "%s %s %s %s QUIT %c" # if (CLIENTS_CHANNEL_LEVEL & CCL_QUITINFO) " :%s" # endif , sptr->user->uid, sptr->name, sptr->user->username, sptr->user->host, sptr->exitc # if (CLIENTS_CHANNEL_LEVEL & CCL_QUITINFO) , comment # endif ); # endif } else if (!IsService(sptr)) { # if defined(FNAME_CONNLOG) || defined(USE_SERVICES) || \ (defined(USE_SYSLOG) && defined(SYSLOG_CONN)) if (sptr->exitc == '\0' || sptr->exitc == EXITC_REG) { sptr->exitc = EXITC_UNDEF; } sendto_flog(sptr, sptr->exitc, sptr->user && sptr->user->username ? sptr->user->username : "", #ifdef UNIXPORT (IsUnixSocket(sptr)) ? me.sockhost : #endif ((sptr->hostp) ? sptr->hostp->h_name : sptr->sockhost)); # endif } #endif if (MyConnect(sptr)) { if (IsPerson(sptr)) { istat.is_myclnt--; } else if (IsServer(sptr)) { istat.is_myserv--; } else if (IsService(sptr)) { istat.is_myservice--; } else { istat.is_unknown--; } if (istat.is_myclnt % CLCHNO == 0 && istat.is_myclnt != istat.is_l_myclnt) { sendto_flag(SCH_NOTICE, "Local %screase from %d to %d clients " "in %d seconds", istat.is_myclnt>istat.is_l_myclnt?"in":"de", istat.is_l_myclnt, istat.is_myclnt, timeofday - istat.is_l_myclnt_t); istat.is_l_myclnt_t = timeofday; istat.is_l_myclnt = istat.is_myclnt; } /* Send SQUIT message to 2.11 servers to tell them * the squit reason for rebroadcast on the other side * - jv */ if (IsServer(sptr)) { sendto_one(sptr, ":%s SQUIT %s :%s", me.serv->sid, sptr->serv->sid, comment); } if (cptr != NULL && sptr != cptr) { sendto_one(sptr, "ERROR :Closing Link: " "%s %s (%s)", get_client_name(sptr,FALSE), cptr->name, comment); } else { sendto_one(sptr, "ERROR :Closing Link: %s (%s)", get_client_name(sptr,FALSE), comment); } if (sptr->auth != sptr->username) { istat.is_authmem -= strlen(sptr->auth) + 1; istat.is_auth -= 1; MyFree(sptr->auth); sptr->auth = sptr->username; } } /* ** Currently only server connections can have ** depending remote clients here, but it does no ** harm to check for all local clients. In ** future some other clients than servers might ** have remotes too... ** now, I think it harms big client servers... - krys ** ** Close the Client connection first and mark it ** so that no messages are attempted to send to it. ** (The following *must* make MyConnect(sptr) == FALSE!). ** It also makes sptr->from == NULL, thus it's unnecessary ** to test whether "sptr != acptr" in the following loops. */ close_connection(sptr); } /* if (MyConnect(sptr) */ if (IsServer(sptr)) { /* Remove all dependent servers and clients. */ if (!IsMasked(sptr)) { sprintf(comment1, "%s %s", sptr->serv->up->name, sptr->name); } else { /* It was a masked server, the squit reason should ** give the right quit reason for clients. */ strncpyzt(comment1, comment, sizeof(comment1)); } /* cptr != sptr means non-local server */ if (cptr != sptr && nextconnect == 0 && find_conf_name(sptr->name, (CONF_CONNECT_SERVER|CONF_ZCONNECT_SERVER))) { /* try AC */ nextconnect = timeofday + HANGONRETRYDELAY; } exit_server(sptr, sptr, from, comment, comment1); check_split(); if ((cptr == sptr)) { /* It serves no purpose. --B. sendto_flag(SCH_SERVER, "Sending SQUIT %s (%s)", cptr->name, comment); */ return FLUSH_BUFFER; } return 0; } /* ** Try to guess from comment if the client is exiting ** normally (KILL or issued QUIT), or if it is splitting ** It requires comment for splitting users to be ** "server.some.where splitting.some.where" */ comment1[0] = '\0'; if ((sptr->flags & FLAGS_KILLED) == 0) { if (comment[0] == '"') { /* definitely user quit, see m_quit */ sptr->flags |= FLAGS_QUIT; } else { const char *c = comment; int i = 0; while (*c && *c != ' ') if (*c++ == '.') i++; if (*c++ && i) { i = 0; while (*c && *c != ' ') if (*c++ == '.') i++; if (!i || *c) sptr->flags |= FLAGS_QUIT; } else { sptr->flags |= FLAGS_QUIT; } } if (sptr == cptr && !(sptr->flags & FLAGS_QUIT)) { /* ** This will avoid nick delay to be abused by ** letting local users put a comment looking ** like a server split. */ strncpyzt(comment1, comment, HOSTLEN + HOSTLEN); strcat(comment1, " "); sptr->flags |= FLAGS_QUIT; } } exit_one_client(cptr, sptr, from, (*comment1) ? comment1 : comment); /* XXX: we probably should not call it every client exit */ /* checking every server quit should suffice --B. */ /* check_split(); */ return cptr == sptr ? FLUSH_BUFFER : 0; }
void init_rpc_pipe_hnd(void) { bmap = bitmap_allocate(MAX_OPEN_PIPES); if (!bmap) exit_server("out of memory in init_rpc_pipe_hnd\n"); }
int main(int argc, char *argv[]) #endif { fd_set rfds; struct timeval tv; int server_socket = -1; int bytes, retval; struct dhcpMessage packet; unsigned char *state; unsigned char *server_id, *requested, *hostname; u_int32_t server_id_align, requested_align; unsigned long timeout_end; struct option_set *option; struct dhcpOfferedAddr *lease; int pid_fd; int max_sock; int sig; /* DD-WRT (belanger) : ignore signals until we're ready */ signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGTERM, SIG_IGN); OPEN_LOG("udhcpd"); LOG(LOG_INFO, "udhcp server (v%s) started", VERSION); memset(&server_config, 0, sizeof(struct server_config_t)); if (argc < 2) read_config(DHCPD_CONF_FILE); else read_config(argv[1]); pid_fd = pidfile_acquire(server_config.pidfile); pidfile_write_release(pid_fd); if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) { memcpy(&server_config.lease, option->data + 2, 4); server_config.lease = ntohl(server_config.lease); } else server_config.lease = LEASE_TIME; leases = malloc(sizeof(struct dhcpOfferedAddr) * server_config.max_leases); memset(leases, 0, sizeof(struct dhcpOfferedAddr) * server_config.max_leases); read_leases(server_config.lease_file); read_statics(server_config.statics_file); /* DD-WRT (belanger) : write leases now */ write_leases(); if (read_interface(server_config.interface, &server_config.ifindex, &server_config.server, server_config.arp) < 0) exit_server(1); #ifndef DEBUGGING pid_fd = pidfile_acquire(server_config.pidfile); /* hold lock during fork. */ if (daemon(0, 0) == -1) { perror("fork"); exit_server(1); } pidfile_write_release(pid_fd); #endif socketpair(AF_UNIX, SOCK_STREAM, 0, signal_pipe); signal(SIGUSR1, signal_handler); signal(SIGUSR2, signal_handler); signal(SIGTERM, signal_handler); signal(SIGHUP, signal_handler); timeout_end = get_time(0) + server_config.auto_time; while(1) { /* loop until universe collapses */ if (server_socket < 0) if ((server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface)) < 0) { LOG(LOG_ERR, "FATAL: couldn't create server socket, %s", strerror(errno)); exit_server(0); } FD_ZERO(&rfds); FD_SET(server_socket, &rfds); FD_SET(signal_pipe[0], &rfds); if (server_config.auto_time) { tv.tv_sec = timeout_end - get_time(0); tv.tv_usec = 0; } if (!server_config.auto_time || tv.tv_sec > 0) { max_sock = server_socket > signal_pipe[0] ? server_socket : signal_pipe[0]; retval = select(max_sock + 1, &rfds, NULL, NULL, server_config.auto_time ? &tv : NULL); } else retval = 0; /* If we already timed out, fall through */ if (retval == 0) { write_leases(); timeout_end = get_time(0) + server_config.auto_time; continue; } else if (retval < 0 && errno != EINTR) { DEBUG(LOG_INFO, "error on select"); continue; } if (FD_ISSET(signal_pipe[0], &rfds)) { if (read(signal_pipe[0], &sig, sizeof(sig)) < 0) continue; /* probably just EINTR */ switch (sig) { case SIGUSR1: LOG(LOG_INFO, "Received a SIGUSR1"); write_leases(); /* why not just reset the timeout, eh */ timeout_end = get_time(0) + server_config.auto_time; continue; case SIGUSR2: LOG(LOG_INFO, "Received a SIGUSR2"); delete_leases(); continue; case SIGHUP: LOG(LOG_INFO, "Received a SIGHUP"); read_leases(server_config.lease_file); read_statics(server_config.statics_file); continue; case SIGTERM: LOG(LOG_INFO, "Received a SIGTERM"); exit_server(0); } } if ((bytes = get_packet(&packet, server_socket)) < 0) { /* this waits for a packet - idle */ if (bytes == -1 && errno != EINTR) { DEBUG(LOG_INFO, "error on read, %s, reopening socket", strerror(errno)); close(server_socket); server_socket = -1; } continue; } if ((state = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { DEBUG(LOG_ERR, "couldn't get option from packet, ignoring"); continue; } hostname = get_option(&packet, DHCP_HOST_NAME); /* ADDME: look for a static lease */ /* If a hostname is supplied, and that hostname is a static lease, and that static lease has an FF:FF:FF:FF:FF:FF MAC address, then use that entry. */ if ( NULL == hostname || NULL == (lease = find_lease_by_hostname(hostname)) || (lease->expires != EXPIRES_NEVER) || 0 != memcmp(lease->chaddr, MAC_BCAST_ADDR, strlen(MAC_BCAST_ADDR))) { /* Otherwise, look up the table using the supplied MAC address. */ lease = find_lease_by_chaddr(packet.chaddr); } switch (state[0]) { case DHCPDISCOVER: LOG(LOG_INFO,"received DISCOVER from %02x:%02x:%02x:%02x:%02x:%02x", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); // modify by honor if (sendOffer(&packet, lease) < 0) { LOG(LOG_ERR, "send OFFER failed"); } break; case DHCPREQUEST: requested = get_option(&packet, DHCP_REQUESTED_IP); server_id = get_option(&packet, DHCP_SERVER_ID); if (requested) memcpy(&requested_align, requested, 4); if (server_id) memcpy(&server_id_align, server_id, 4); if (requested) { struct in_addr addr; addr.s_addr = requested_align; LOG(LOG_INFO, "received REQUEST for %s from %02x:%02x:%02x:%02x:%02x:%02x", inet_ntoa(addr), packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); } else { LOG(LOG_INFO, "received REQUEST from %02x:%02x:%02x:%02x:%02x:%02x", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); } if (lease) { /*ADDME: or static lease */ if (server_id) { /* SELECTING State */ DEBUG(LOG_INFO, "server_id = %08x", ntohl(server_id_align)); if (server_id_align == server_config.server && requested && requested_align == lease->yiaddr) { sendACK(&packet, lease->yiaddr); } else sendNAK(&packet); //Sveasoft - shouldn't we let them know we don't like the request? } else { if (requested) { /* INIT-REBOOT State */ if (lease->yiaddr == requested_align) sendACK(&packet, lease->yiaddr); else sendNAK(&packet); } else { /* RENEWING or REBINDING State */ if (lease->yiaddr == packet.ciaddr) sendACK(&packet, lease->yiaddr); // else if (!packet.ciaddr) /* Accept an invalid request in RENEWING state, where the ciaddr should be set, but is not. */ /* e.g. Linksys Print Server */ // sendACK(&packet, lease->yiaddr); //note: let's not support broken stuff - Sveasoft 2005-01-19 else { /* don't know what to do!!!! */ sendNAK(&packet); } } } if (lease->expires != EXPIRES_NEVER) { /* Don't change hostname of static leases */ if (hostname) { bytes = hostname[-1]; if (bytes >= (int) sizeof(lease->hostname)) bytes = sizeof(lease->hostname) - 1; strncpy(lease->hostname, hostname, bytes); lease->hostname[bytes] = '\0'; } else lease->hostname[0] = '\0'; } /* what to do if we have no record of the client */ } else if (server_id) { /* SELECTING State */ sendNAK(&packet); // by honor } else if (requested) { /* INIT-REBOOT State */ if ((lease = find_lease_by_yiaddr(requested_align))) { if (lease_expired(lease)) { /* probably best if we drop this lease */ memset(lease->chaddr, 0, 16); /* make some contention for this address */ } else sendNAK(&packet); } else if (requested_align < server_config.start || requested_align > server_config.end) { sendNAK(&packet); } else { sendNAK(&packet); } } else if (packet.ciaddr) { /* RENEWING or REBINDING State */ sendNAK(&packet); } break; case DHCPDECLINE: LOG(LOG_INFO,"received DECLINE from %02x:%02x:%02x:%02x:%02x:%02x", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); // modify by honor if (lease && lease->expires != EXPIRES_NEVER) { memset(lease->chaddr, 0, 16); lease->expires = get_time(0) + server_config.decline_time; } break; case DHCPRELEASE: LOG(LOG_INFO,"received RELEASE from %02x:%02x:%02x:%02x:%02x:%02x", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); // modify by honor if (lease && lease->expires != EXPIRES_NEVER) lease->expires = get_time(0); break; case DHCPINFORM: LOG(LOG_INFO,"received INFORM from %02x:%02x:%02x:%02x:%02x:%02x", packet.chaddr[0], packet.chaddr[1], packet.chaddr[2], packet.chaddr[3], packet.chaddr[4], packet.chaddr[5]); // modify by honor send_inform(&packet); break; default: LOG(LOG_WARNING, "unsupported DHCP message (%02x) -- ignoring", state[0]); } } return 0; }
void reply_negprot(struct smb_request *req) { int choice= -1; int chosen_level = -1; int protocol; const char *p; int arch = ARCH_ALL; int num_cliprotos; char **cliprotos; int i; size_t converted_size; struct smbd_server_connection *sconn = req->sconn; START_PROFILE(SMBnegprot); if (sconn->smb1.negprot.done) { END_PROFILE(SMBnegprot); exit_server_cleanly("multiple negprot's are not permitted"); } sconn->smb1.negprot.done = true; if (req->buflen == 0) { DEBUG(0, ("negprot got no protocols\n")); reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBnegprot); return; } if (req->buf[req->buflen-1] != '\0') { DEBUG(0, ("negprot protocols not 0-terminated\n")); reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBnegprot); return; } p = (const char *)req->buf + 1; num_cliprotos = 0; cliprotos = NULL; while (smbreq_bufrem(req, p) > 0) { char **tmp; tmp = talloc_realloc(talloc_tos(), cliprotos, char *, num_cliprotos+1); if (tmp == NULL) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(cliprotos); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBnegprot); return; } cliprotos = tmp; if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p, &converted_size)) { DEBUG(0, ("pull_ascii_talloc failed\n")); TALLOC_FREE(cliprotos); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBnegprot); return; } DEBUG(3, ("Requested protocol [%s]\n", cliprotos[num_cliprotos])); num_cliprotos += 1; p += strlen(p) + 2; } for (i=0; i<num_cliprotos; i++) { if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a")) arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K ); else if (strcsequal(cliprotos[i], "DOS LM1.2X002")) arch &= ( ARCH_WFWG | ARCH_WIN95 ); else if (strcsequal(cliprotos[i], "DOS LANMAN2.1")) arch &= ( ARCH_WFWG | ARCH_WIN95 ); else if (strcsequal(cliprotos[i], "NT LM 0.12")) arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS); else if (strcsequal(cliprotos[i], "SMB 2.001")) arch = ARCH_VISTA; else if (strcsequal(cliprotos[i], "LANMAN2.1")) arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 ); else if (strcsequal(cliprotos[i], "LM1.2X002")) arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 ); else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03")) arch &= ARCH_WINNT; else if (strcsequal(cliprotos[i], "XENIX CORE")) arch &= ( ARCH_WINNT | ARCH_OS2 ); else if (strcsequal(cliprotos[i], "Samba")) { arch = ARCH_SAMBA; break; } else if (strcsequal(cliprotos[i], "POSIX 2")) { arch = ARCH_CIFSFS; break; } } /* CIFSFS can send one arch only, NT LM 0.12. */ if (i == 1 && (arch & ARCH_CIFSFS)) { arch = ARCH_CIFSFS; } switch ( arch ) { case ARCH_CIFSFS: set_remote_arch(RA_CIFSFS); break; case ARCH_SAMBA: set_remote_arch(RA_SAMBA); break; case ARCH_WFWG: set_remote_arch(RA_WFWG); break; case ARCH_WIN95: set_remote_arch(RA_WIN95); break; case ARCH_WINNT: if(req->flags2 == FLAGS2_WIN2K_SIGNATURE) set_remote_arch(RA_WIN2K); else set_remote_arch(RA_WINNT); break; case ARCH_WIN2K: /* Vista may have been set in the negprot so don't override it here */ if ( get_remote_arch() != RA_VISTA ) set_remote_arch(RA_WIN2K); break; case ARCH_VISTA: set_remote_arch(RA_VISTA); break; case ARCH_OS2: set_remote_arch(RA_OS2); break; default: set_remote_arch(RA_UNKNOWN); break; } /* possibly reload - change of architecture */ reload_services(sconn, conn_snum_used, true); /* moved from the netbios session setup code since we don't have that when the client connects to port 445. Of course there is a small window where we are listening to messages -- jerry */ serverid_register(messaging_server_id(sconn->msg_ctx), FLAG_MSG_GENERAL|FLAG_MSG_SMBD |FLAG_MSG_PRINT_GENERAL); /* Check for protocols, most desirable first */ for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) { i = 0; if ((supported_protocols[protocol].protocol_level <= lp_server_max_protocol()) && (supported_protocols[protocol].protocol_level >= lp_server_min_protocol())) while (i < num_cliprotos) { if (strequal(cliprotos[i],supported_protocols[protocol].proto_name)) { choice = i; chosen_level = supported_protocols[protocol].protocol_level; } i++; } if(choice != -1) break; } if(choice != -1) { fstrcpy(remote_proto,supported_protocols[protocol].short_name); reload_services(sconn, conn_snum_used, true); supported_protocols[protocol].proto_reply_fn(req, choice); DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); } else { DEBUG(0,("No protocol supported !\n")); reply_outbuf(req, 1, 0); SSVAL(req->outbuf, smb_vwv0, choice); } DEBUG( 5, ( "negprot index=%d\n", choice ) ); if ((lp_server_signing() == SMB_SIGNING_REQUIRED) && (chosen_level < PROTOCOL_NT1)) { exit_server_cleanly("SMB signing is required and " "client negotiated a downlevel protocol"); } TALLOC_FREE(cliprotos); if (lp_async_smb_echo_handler() && (chosen_level < PROTOCOL_SMB2_02) && !fork_echo_handler(sconn)) { exit_server("Failed to fork echo handler"); } END_PROFILE(SMBnegprot); return; }
void sigint(void) { //ctrl-c pressed exit_server(); }
/** * Initialize the application configuration based on the config file content * Read the config file, get mandatory variables and devices */ int build_config_from_file(struct config_elements * config) { config_t cfg; config_setting_t * root, * database; const char * cur_prefix, * cur_log_mode, * cur_log_level, * cur_log_file = NULL, * one_log_mode, * db_type, * db_sqlite_path, * db_mariadb_host = NULL, * db_mariadb_user = NULL, * db_mariadb_password = NULL, * db_mariadb_dbname = NULL; int db_mariadb_port = 0; config_init(&cfg); if (!config_read_file(&cfg, config->config_file)) { fprintf(stderr, "Error parsing config file %s\nOn line %d error: %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); config_destroy(&cfg); return 0; } if (config->instance->port == -1) { // Get Port number to listen to int port; config_lookup_int(&cfg, "port", &port); config->instance->port = port; } if (config->url_prefix == NULL) { // Get prefix url if (config_lookup_string(&cfg, "url_prefix", &cur_prefix)) { config->url_prefix = o_strdup(cur_prefix); if (config->url_prefix == NULL) { fprintf(stderr, "Error allocating config->url_prefix, exiting\n"); config_destroy(&cfg); return 0; } } } if (config->log_mode == Y_LOG_MODE_NONE) { // Get log mode if (config_lookup_string(&cfg, "log_mode", &cur_log_mode)) { one_log_mode = strtok((char *)cur_log_mode, ","); while (one_log_mode != NULL) { if (0 == strncmp("console", one_log_mode, strlen("console"))) { config->log_mode |= Y_LOG_MODE_CONSOLE; } else if (0 == strncmp("syslog", one_log_mode, strlen("syslog"))) { config->log_mode |= Y_LOG_MODE_SYSLOG; } else if (0 == strncmp("file", one_log_mode, strlen("file"))) { config->log_mode |= Y_LOG_MODE_FILE; // Get log file path if (config->log_file == NULL) { if (config_lookup_string(&cfg, "log_file", &cur_log_file)) { config->log_file = o_strdup(cur_log_file); if (config->log_file == NULL) { fprintf(stderr, "Error allocating config->log_file, exiting\n"); config_destroy(&cfg); return 0; } } } } one_log_mode = strtok(NULL, ","); } } } if (config->log_level == Y_LOG_LEVEL_NONE) { // Get log level if (config_lookup_string(&cfg, "log_level", &cur_log_level)) { if (0 == strncmp("NONE", cur_log_level, strlen("NONE"))) { config->log_level = Y_LOG_LEVEL_NONE; } else if (0 == strncmp("ERROR", cur_log_level, strlen("ERROR"))) { config->log_level = Y_LOG_LEVEL_ERROR; } else if (0 == strncmp("WARNING", cur_log_level, strlen("WARNING"))) { config->log_level = Y_LOG_LEVEL_WARNING; } else if (0 == strncmp("INFO", cur_log_level, strlen("INFO"))) { config->log_level = Y_LOG_LEVEL_INFO; } else if (0 == strncmp("DEBUG", cur_log_level, strlen("DEBUG"))) { config->log_level = Y_LOG_LEVEL_DEBUG; } } } if (!y_init_logs(GARETH_LOG_NAME, config->log_mode, config->log_level, config->log_file, "Starting Gareth alert and messenger service")) { fprintf(stderr, "Error initializing logs\n"); exit_server(&config, GARETH_ERROR); } root = config_root_setting(&cfg); database = config_setting_get_member(root, "database"); if (database != NULL) { if (config_setting_lookup_string(database, "type", &db_type) == CONFIG_TRUE) { if (0 == strncmp(db_type, "sqlite3", strlen("sqlite3"))) { if (config_setting_lookup_string(database, "path", &db_sqlite_path) == CONFIG_TRUE) { config->conn = h_connect_sqlite(db_sqlite_path); if (config->conn == NULL) { config_destroy(&cfg); fprintf(stderr, "Error opening sqlite database %s\n", db_sqlite_path); return 0; } } else { config_destroy(&cfg); fprintf(stderr, "Error, no sqlite database specified\n"); return 0; } } else if (0 == strncmp(db_type, "mariadb", strlen("mariadb"))) { config_setting_lookup_string(database, "host", &db_mariadb_host); config_setting_lookup_string(database, "user", &db_mariadb_user); config_setting_lookup_string(database, "password", &db_mariadb_password); config_setting_lookup_string(database, "dbname", &db_mariadb_dbname); config_setting_lookup_int(database, "port", &db_mariadb_port); config->conn = h_connect_mariadb(db_mariadb_host, db_mariadb_user, db_mariadb_password, db_mariadb_dbname, db_mariadb_port, NULL); if (config->conn == NULL) { fprintf(stderr, "Error opening mariadb database %s\n", db_mariadb_dbname); config_destroy(&cfg); return 0; } } else { config_destroy(&cfg); fprintf(stderr, "Error, database type unknown\n"); return 0; } } else { config_destroy(&cfg); fprintf(stderr, "Error, no database type found\n"); return 0; } } else { config_destroy(&cfg); fprintf(stderr, "Error, no database setting found\n"); return 0; } config_destroy(&cfg); return 1; }
/* * Exit one client, local or remote. Assuming all dependants have * been already removed, and socket closed for local client. */ static void exit_one_client(aClient *cptr, aClient *sptr, aClient *from, char *comment) { Link *lp; /* * For a server or user quitting, propogate the information to * other servers (except to the one where is came from (cptr)) */ if (IsMe(sptr)) { sendto_ops("ERROR: tried to exit me! : %s", comment); return; /* ...must *never* exit self!! */ } else if (IsServer(sptr)) { #ifdef ALWAYS_SEND_DURING_SPLIT currently_processing_netsplit = YES; #endif exit_server(cptr, sptr, from, comment); #ifdef ALWAYS_SEND_DURING_SPLIT currently_processing_netsplit = NO; #endif return; } else if (!(IsPerson(sptr))) /* * ...this test is *dubious*, would need * some thought.. but for * now it plugs a * nasty hole in the server... --msa */ ; /* Nothing */ else if (sptr->name[0]) { /* ...just clean all others with QUIT... */ /* * If this exit is generated from "m_kill", then there is no * sense in sending the QUIT--KILL's have been sent instead. */ if ((sptr->flags & FLAGS_KILLED) == 0) { sendto_serv_butone(cptr, ":%s QUIT :%s", sptr->name, comment); } /* * * If a person is on a channel, send a QUIT notice * to every * client (person) on the same channel (so * that the client can * show the "**signoff" message). * (Note: The notice is to the * local clients *only*) */ if (sptr->user) { send_part_to_common_channels(sptr, comment); send_quit_to_common_channels(sptr, comment); while ((lp = sptr->user->channel)) remove_user_from_channel(sptr, lp->value.chptr); clones_remove(sptr); #ifdef RWHO_PROBABILITY probability_remove(sptr); #endif /* Clean up invitefield */ while ((lp = sptr->user->invited)) del_invite(sptr, lp->value.chptr); /* Clean up silences */ while ((lp = sptr->user->silence)) del_silence(sptr, lp->value.cp); remove_dcc_references(sptr); /* again, this is all that is needed */ } } /* Remove sptr from the client list */ if (del_from_client_hash_table(sptr->name, sptr) != 1) { Debug((DEBUG_ERROR, "%#x !in tab %s[%s] %#x %#x %#x %d %d %#x", sptr, sptr->name, sptr->from ? sptr->from->sockhost : "??host", sptr->from, sptr->next, sptr->prev, sptr->fd, sptr->status, sptr->user)); } /* remove user from watchlists */ if(IsRegistered(sptr)) hash_check_watch(sptr, RPL_LOGOFF); remove_client_from_list(sptr); return; }
/** * Initialize the application configuration based on the command line parameters */ int build_config_from_args(int argc, char ** argv, struct config_elements * config) { int next_option; const char * short_options = "c::p::b::u::d::a::s::m::l::f::r::h::"; char * tmp = NULL, * to_free = NULL, * one_log_mode = NULL; static const struct option long_options[]= { {"config-file", optional_argument,NULL, 'c'}, {"port", optional_argument,NULL, 'p'}, {"url-prefix", optional_argument,NULL, 'u'}, {"log-mode", optional_argument,NULL, 'm'}, {"log-level", optional_argument,NULL, 'l'}, {"log-file", optional_argument,NULL, 'f'}, {"help", optional_argument,NULL, 'h'}, {NULL, 0, NULL, 0} }; if (config != NULL) { do { next_option = getopt_long(argc, argv, short_options, long_options, NULL); switch (next_option) { case 'c': if (optarg != NULL) { config->config_file = o_strdup(optarg); if (config->config_file == NULL) { fprintf(stderr, "Error allocating config->config_file, exiting\n"); exit_server(&config, GARETH_STOP); } } else { fprintf(stderr, "Error!\nNo config file specified\n"); return 0; } break; case 'p': if (optarg != NULL) { config->instance->port = strtol(optarg, NULL, 10); if (config->instance->port <= 0 || config->instance->port > 65535) { fprintf(stderr, "Error!\nInvalid TCP Port number\n\tPlease specify an integer value between 1 and 65535"); return 0; } } else { fprintf(stderr, "Error!\nNo TCP Port number specified\n"); return 0; } break; case 'u': if (optarg != NULL) { config->url_prefix = o_strdup(optarg); if (config->url_prefix == NULL) { fprintf(stderr, "Error allocating config->url_prefix, exiting\n"); exit_server(&config, GARETH_STOP); } } else { fprintf(stderr, "Error!\nNo URL prefix specified\n"); return 0; } break; case 'm': if (optarg != NULL) { tmp = o_strdup(optarg); if (tmp == NULL) { fprintf(stderr, "Error allocating log_mode, exiting\n"); exit_server(&config, GARETH_STOP); } one_log_mode = strtok(tmp, ","); while (one_log_mode != NULL) { if (0 == strncmp("console", one_log_mode, strlen("console"))) { config->log_mode |= Y_LOG_MODE_CONSOLE; } else if (0 == strncmp("syslog", one_log_mode, strlen("syslog"))) { config->log_mode |= Y_LOG_MODE_SYSLOG; } else if (0 == strncmp("file", one_log_mode, strlen("file"))) { config->log_mode |= Y_LOG_MODE_FILE; } one_log_mode = strtok(NULL, ","); } free(to_free); } else { fprintf(stderr, "Error!\nNo mode specified\n"); return 0; } break; case 'l': if (optarg != NULL) { if (0 == strncmp("NONE", optarg, strlen("NONE"))) { config->log_level = Y_LOG_LEVEL_NONE; } else if (0 == strncmp("ERROR", optarg, strlen("ERROR"))) { config->log_level = Y_LOG_LEVEL_ERROR; } else if (0 == strncmp("WARNING", optarg, strlen("WARNING"))) { config->log_level = Y_LOG_LEVEL_WARNING; } else if (0 == strncmp("INFO", optarg, strlen("INFO"))) { config->log_level = Y_LOG_LEVEL_INFO; } else if (0 == strncmp("DEBUG", optarg, strlen("DEBUG"))) { config->log_level = Y_LOG_LEVEL_DEBUG; } } else { fprintf(stderr, "Error!\nNo log level specified\n"); return 0; } break; case 'f': if (optarg != NULL) { config->log_file = o_strdup(optarg); if (config->log_file == NULL) { fprintf(stderr, "Error allocating config->log_file, exiting\n"); exit_server(&config, GARETH_STOP); } } else { fprintf(stderr, "Error!\nNo log file specified\n"); return 0; } break; case 'h': exit_server(&config, GARETH_STOP); break; } } while (next_option != -1); // If none exists, exit failure if (config->config_file == NULL) { fprintf(stderr, "No configuration file found, please specify a configuration file path\n"); return 0; } return 1; } else { return 0; } }
static int reply_nt1(char *inbuf, char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ| CAP_LEVEL_II_OPLOCKS; int secword=0; time_t t = time(NULL); char *p, *q; BOOL negotiate_spnego = False; global_encrypted_passwords_negotiated = lp_encrypted_passwords(); /* do spnego in user level security if the client supports it and we can do encrypted passwords */ if (global_encrypted_passwords_negotiated && (lp_security() != SEC_SHARE) && lp_use_spnego() && (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { negotiate_spnego = True; capabilities |= CAP_EXTENDED_SECURITY; add_to_common_flags2(FLAGS2_EXTENDED_SECURITY); /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply (already partially constructed. */ SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY); } capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE; if (lp_unix_extensions()) { capabilities |= CAP_UNIX; } if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS; if (SMB_OFF_T_BITS == 64) capabilities |= CAP_LARGE_FILES; if (lp_readraw() && lp_writeraw()) capabilities |= CAP_RAW_MODE; if (lp_nt_status_support()) capabilities |= CAP_STATUS32; if (lp_host_msdfs()) capabilities |= CAP_DFS; if (lp_security() >= SEC_USER) secword |= NEGOTIATE_SECURITY_USER_LEVEL; if (global_encrypted_passwords_negotiated) secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; if (lp_server_signing()) { if (lp_security() >= SEC_USER) { secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED; /* No raw mode with smb signing. */ capabilities &= ~CAP_RAW_MODE; if (lp_server_signing() == Required) secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED; srv_set_signing_negotiated(); } else { DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n")); if (lp_server_signing() == Required) { exit_server("reply_nt1: smb signing required and share level security selected."); } } } set_message(outbuf,17,0,True); SCVAL(outbuf,smb_vwv1,secword); Protocol = PROTOCOL_NT1; SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */ SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */ SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */ SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ put_long_date(outbuf+smb_vwv11+1,t); SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); p = q = smb_buf(outbuf); if (!negotiate_spnego) { /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { /* note that we do not send a challenge at all if we are using plaintext */ get_challenge(p); SSVALS(outbuf,smb_vwv16+1,8); p += 8; } p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN); DEBUG(3,("not using SPNEGO\n")); } else { int len = negprot_spnego(p); SSVALS(outbuf,smb_vwv16+1,len); p += len; DEBUG(3,("using SPNEGO\n")); } SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */ set_message_end(outbuf, p); return (smb_len(outbuf)+4); }