/* Call the agent to learn about a smartcard */ int agent_learn (struct agent_card_info_s *info) { int rc; rc = start_agent (1); if (rc) return rc; /* Send the serialno command to initialize the connection. We don't care about the data returned. If the card has already been initialized, this is a very fast command. The main reason we need to do this here is to handle a card removed case so that an "l" command in --card-edit can be used to show ta newly inserted card. We request the openpgp card because that is what we expect. */ rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp", NULL, NULL, NULL, NULL, NULL, NULL); if (rc) return rc; memset (info, 0, sizeof *info); rc = assuan_transact (agent_ctx, "SCD LEARN --force", dummy_data_cb, NULL, default_inq_cb, NULL, learn_status_cb, info); /* Also try to get the key attributes. */ if (!rc) agent_scd_getattr ("KEY-ATTR", info); return rc; }
/* Return the S2K iteration count as computed by gpg-agent. */ gpg_error_t agent_get_s2k_count (unsigned long *r_count) { gpg_error_t err; membuf_t data; char *buf; *r_count = 0; err = start_agent (0); if (err) return err; init_membuf (&data, 32); err = assuan_transact (agent_ctx, "GETINFO s2k_count", membuf_data_cb, &data, NULL, NULL, NULL, NULL); if (err) xfree (get_membuf (&data, NULL)); else { put_membuf (&data, "", 1); buf = get_membuf (&data, NULL); if (!buf) err = gpg_error_from_syserror (); else { *r_count = strtoul (buf, NULL, 10); xfree (buf); } } return err; }
/* Send a WRITECERT command to the SCdaemon. */ int agent_scd_writecert (const char *certidstr, const unsigned char *certdata, size_t certdatalen) { int rc; char line[ASSUAN_LINELENGTH]; struct writecert_parm_s parms; rc = start_agent (1); if (rc) return rc; memset (&parms, 0, sizeof parms); snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr); line[DIM(line)-1] = 0; parms.ctx = agent_ctx; parms.certdata = certdata; parms.certdatalen = certdatalen; rc = assuan_transact (agent_ctx, line, NULL, NULL, inq_writecert_parms, &parms, NULL, NULL); return rc; }
/* Send a WRITEKEY command to the SCdaemon. */ int agent_scd_writekey (int keyno, const char *serialno, const unsigned char *keydata, size_t keydatalen) { int rc; char line[ASSUAN_LINELENGTH]; struct writekey_parm_s parms; (void)serialno; rc = start_agent (1); if (rc) return rc; memset (&parms, 0, sizeof parms); snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno); line[DIM(line)-1] = 0; parms.ctx = agent_ctx; parms.keydata = keydata; parms.keydatalen = keydatalen; rc = assuan_transact (agent_ctx, line, NULL, NULL, inq_writekey_parms, &parms, NULL, NULL); status_sc_op_failure (rc); return rc; }
/* Send a READCERT command to the SCdaemon. */ int agent_scd_readcert (const char *certidstr, void **r_buf, size_t *r_buflen) { int rc; char line[ASSUAN_LINELENGTH]; membuf_t data; size_t len; *r_buf = NULL; rc = start_agent (1); if (rc) return rc; init_membuf (&data, 2048); snprintf (line, DIM(line)-1, "SCD READCERT %s", certidstr); line[DIM(line)-1] = 0; rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data, default_inq_cb, NULL, NULL, NULL); if (rc) { xfree (get_membuf (&data, &len)); return rc; } *r_buf = get_membuf (&data, r_buflen); if (!*r_buf) return gpg_error (GPG_ERR_ENOMEM); return 0; }
/* Send a sign command to the scdaemon via gpg-agent's pass thru mechanism. */ int agent_scd_pksign (const char *serialno, int hashalgo, const unsigned char *indata, size_t indatalen, unsigned char **r_buf, size_t *r_buflen) { int rc, i; char *p, line[ASSUAN_LINELENGTH]; membuf_t data; size_t len; /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */ *r_buf = NULL; *r_buflen = 0; rc = start_agent (1); if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT || gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED) rc = 0; /* We check later. */ if (rc) return rc; if (indatalen*2 + 50 > DIM(line)) return gpg_error (GPG_ERR_GENERAL); rc = select_openpgp (serialno); if (rc) return rc; sprintf (line, "SCD SETDATA "); p = line + strlen (line); for (i=0; i < indatalen ; i++, p += 2 ) sprintf (p, "%02X", indata[i]); rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) return rc; init_membuf (&data, 1024); #if 0 if (!hashalgo) /* Temporary test hack. */ snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno); else #endif snprintf (line, DIM(line)-1, "SCD PKSIGN %s %s", hash_algo_option (hashalgo), serialno); line[DIM(line)-1] = 0; rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data, default_inq_cb, NULL, NULL, NULL); if (rc) { xfree (get_membuf (&data, &len)); } else *r_buf = get_membuf (&data, r_buflen); status_sc_op_failure (rc); return rc; }
INTERNAL void agentman(EVENT_AGENTD_REQ *eagent) { int pid, exitstat; int me; int rc; AGENT_REQ *areq; if (Debug) printf("agentman: starting\n"); /* Copy arg data into active Agent list & unblock parent */ mp_lock(AgentLock); printf("Allocating agent control block\n"); areq = agent_alloc(); if (!areq) { fprintf(stderr, "agentman: can't start %s\n", eagent->module); mp_exit(0); } printf("Initializing agent control block\\n"); memcpy(&areq->ereq, eagent, sizeof(EVENT_AGENTD_REQ)); mp_unlock(AgentLock); /* Unblock parent thread */ mp_incsema(AgentInit); if (Debug) printf("agentman: starting as thread %d.%d\n", getpid(), mp_gettid()); areq->pid = 0; areq->status = AGENTD_AGENT_INIT; areq->start = event_clock(); if (areq->ereq.log[0] && areq->ereq.log[0] != ' ') rc = start_logger(areq, areq->ereq.log, areq->ereq.module, areq->ereq.args, &pid); else rc = start_agent(areq, areq->ereq.module, areq->ereq.args, &pid); if (Debug) printf("agentman: thread (%d.%d) done and exiting\n", getpid(), mp_gettid()); /* Copy to obiturary list */ if (++Nrip == MAX_RIP) Nrip = 0; memcpy(Rip, areq, sizeof(AGENT_REQ)); /* Remove entry for this agent */ mp_lock(AgentLock); agent_free(areq); mp_unlock(AgentLock); mp_exit(0); }
/* Send a GENKEY command to the SCdaemon. SERIALNO is not used in this implementation. If CREATEDATE has been given, it will be passed to SCDAEMON so that the key can be created with this timestamp; note the user needs to use the returned timestamp as old versions of scddaemon don't support this option. */ int agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force, const char *serialno, u32 createtime, gcry_sexp_t *r_pubkey) { int rc; char line[ASSUAN_LINELENGTH]; gnupg_isotime_t tbuf; membuf_t data; unsigned char *buf; size_t len; (void)serialno; rc = start_agent (1); if (rc) return rc; if (createtime) epoch2isotime (tbuf, createtime); else *tbuf = 0; memset (info, 0, sizeof *info); snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d", *tbuf? "--timestamp=":"", tbuf, force? "--force":"", keyno); line[DIM(line)-1] = 0; memset (info, 0, sizeof *info); init_membuf_secure (&data, 1024); rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data, default_inq_cb, NULL, scd_genkey_cb, info); status_sc_op_failure (rc); if (rc) { xfree (get_membuf (&data, &len)); } else { buf = get_membuf (&data, &len); if (!buf) return gpg_error_from_syserror (); rc = gcry_sexp_sscan (r_pubkey, NULL, buf, len); xfree (buf); } return rc; }
__attribute__ ((constructor)) void sysinject(void) { printf("Injecting!\n"); fflush(stdout); orig_dlopen = (dlopen_t) dlsym(RTLD_NEXT, "dlopen"); // set settings up set_default_settings(); // Start a thread that will repeatedly poll to see if pImports and whatnot is correct start_agent(); }
/* Send an setattr command to the SCdaemon. SERIALNO is not actually used here but required by gpg 1.4's implementation of this code in cardglue.c. */ int agent_scd_setattr (const char *name, const unsigned char *value, size_t valuelen, const char *serialno) { int rc; char line[ASSUAN_LINELENGTH]; char *p; (void)serialno; if (!*name || !valuelen) return gpg_error (GPG_ERR_INV_VALUE); /* We assume that NAME does not need escaping. */ if (12 + strlen (name) > DIM(line)-1) return gpg_error (GPG_ERR_TOO_LARGE); p = stpcpy (stpcpy (line, "SCD SETATTR "), name); *p++ = ' '; for (; valuelen; value++, valuelen--) { if (p >= line + DIM(line)-5 ) return gpg_error (GPG_ERR_TOO_LARGE); if (*value < ' ' || *value == '+' || *value == '%') { sprintf (p, "%%%02X", *value); p += 3; } else if (*value == ' ') *p++ = '+'; else *p++ = *value; } *p = 0; rc = start_agent (1); if (!rc) { rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL, NULL, NULL); } status_sc_op_failure (rc); return rc; }
/* Perform a CHECKPIN operation. SERIALNO should be the serial number of the card - optionally followed by the fingerprint; however the fingerprint is ignored here. */ int agent_scd_checkpin (const char *serialno) { int rc; char line[ASSUAN_LINELENGTH]; rc = start_agent (1); if (rc) return rc; snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno); line[DIM(line)-1] = 0; rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL, NULL, NULL); status_sc_op_failure (rc); return rc; }
gpg_error_t agent_clear_passphrase (const char *cache_id) { int rc; char line[ASSUAN_LINELENGTH]; if (!cache_id || !*cache_id) return 0; rc = start_agent (0); if (rc) return rc; snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id); line[DIM(line)-1] = 0; return assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL, NULL, NULL); }
/* Ask the agent to pop up a confirmation dialog with the text DESC and an okay and cancel button. */ gpg_error_t gpg_agent_get_confirmation (const char *desc) { int rc; char *tmp; char line[ASSUAN_LINELENGTH]; rc = start_agent (0); if (rc) return rc; tmp = percent_plus_escape (desc); if (!tmp) return gpg_error_from_syserror (); snprintf (line, DIM(line)-1, "GET_CONFIRMATION %s", tmp); line[DIM(line)-1] = 0; xfree (tmp); rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL, NULL, NULL); return rc; }
/* Call the agent to retrieve a data object. This function returns the data in the same structure as used by the learn command. It is allowed to update such a structure using this commmand. */ int agent_scd_getattr (const char *name, struct agent_card_info_s *info) { int rc; char line[ASSUAN_LINELENGTH]; if (!*name) return gpg_error (GPG_ERR_INV_VALUE); /* We assume that NAME does not need escaping. */ if (12 + strlen (name) > DIM(line)-1) return gpg_error (GPG_ERR_TOO_LARGE); stpcpy (stpcpy (line, "SCD GETATTR "), name); rc = start_agent (1); if (rc) return rc; rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL, learn_status_cb, info); return rc; }
/* Change the PIN of an OpenPGP card or reset the retry counter. CHVNO 1: Change the PIN 2: For v1 cards: Same as 1. For v2 cards: Reset the PIN using the Reset Code. 3: Change the admin PIN 101: Set a new PIN and reset the retry counter 102: For v1 cars: Same as 101. For v2 cards: Set a new Reset Code. SERIALNO is not used. */ int agent_scd_change_pin (int chvno, const char *serialno) { int rc; char line[ASSUAN_LINELENGTH]; const char *reset = ""; (void)serialno; if (chvno >= 100) reset = "--reset"; chvno %= 100; rc = start_agent (1); if (rc) return rc; snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno); line[DIM(line)-1] = 0; rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL, NULL, NULL); status_sc_op_failure (rc); return rc; }
void Environment::load_argv(int argc, char** argv) { bool process_xflags = true; state->set_const("ARG0", String::create(state, argv[0])); Array* ary = Array::create(state, argc - 1); int which_arg = 0; for(int i=1; i < argc; i++) { char* arg = argv[i]; if(arg[0] != '-' || strcmp(arg, "--") == 0) { process_xflags = false; } if(process_xflags && strncmp(arg, "-X", 2) == 0) { config_parser.import_line(arg + 2); } else { ary->set(state, which_arg++, String::create(state, arg)->taint(state)); } } state->set_const("ARGV", ary); // Now finish up with the config if(config.qa_port > 0) start_agent(config.qa_port); config_parser.update_configuration(config); if(config.print_config > 1) { std::cout << "========= Configuration =========\n"; config.print(true); std::cout << "=================================\n"; } else if(config.print_config) { config.print(); } }
INTERNAL int start_logger(AGENT_REQ *areq, char *logserver, char *cmd, char *args, int *retpid) { int argc; int logpid; int rc, id, nc; if (Debug) printf("starting logger as proc %d.%d for server %s\n", getpid(), mp_gettid(), logserver); logpid = fork(); if (logpid < 0) { fprintf(stderr, "start_logger: fork failed\n"); perror("start_logger"); return(0); } /* Parent process, send a response to requester and return */ if (logpid > 0) { EVENT_AGENTD_STAT estat; if (areq) { areq->status = AGENTD_AGENT_RUNNING; areq->pid = logpid; estat.reqseq = EventSeq(areq->ereq); estat.tag = areq->ereq.tag; estat.reqtype = AGENTD_CTL_START; estat.result = logpid; estat.rstatus = AGENTD_STATUS_OK; SEND(EventFrom(areq->ereq), AGENTD_STAT, estat); } *retpid = logpid; return(AGENTD_STATUS_OK); } /* * We are now in the logger child proc * - leave agent event server * - join logger server * - start agent task */ event_exit_(); mp_fini(); mp_init(); fprintf(stderr, "logger: running as proc %d.%d\n", getpid(), mp_gettid()); Exitlock = mp_alloclock(); Exitwait = mp_allocsema(); event_tunnel_enable(0); event_init(); event_threadsafe(EVENT_SAFE_ALL); id = event_join(logserver, &nc); if (!id) { fprintf(stderr, "start_logger: couldn't join %s\n", logserver); exit(8); } /* * N.B. For the moment disable the reading of all events * if we need to process incoming events, for some reason, we * should launch a separate thread, similar to the stdout/err * "reader" threads that get started in "start_agent". * Note that start_agent does not return until the subproccess, * i.e. the agent, terminates */ event_select_type(0, ET_MIN, ET_MAX); /*** No, not even these event_select_type(1, ET_AGENTD_MIN, ET_AGENTD_MAX); ***/ event_receive_enable(0); event_flush(1); fprintf(stderr, "logger: %d.%d joined %s as client %d\n", getpid(), mp_gettid(), logserver, id); event_register(LOGGERCLASS, LOGGERSPEC, cmd); rc = start_agent(NULL, cmd, args, retpid); fprintf(stderr, "logger: %d.%d done and exiting with %d\n", getpid(), mp_gettid(), rc); event_leave(); exit(rc); }
/* Ask for a passphrase via gpg-agent. On success the caller needs to free the string stored at R_PASSPHRASE. On error NULL will be stored at R_PASSPHRASE and an appropriate gpg error code is returned. With REPEAT set to 1, gpg-agent will ask the user to repeat the just entered passphrase. CACHE_ID is a gpg-agent style passphrase cache id or NULL. ERR_MSG is a error message to be presented to the user (e.g. "bad passphrase - try again") or NULL. PROMPT is the prompt string to label the entry box, it may be NULL for a default one. DESC_MSG is a longer description to be displayed above the entry box, if may be NULL for a default one. If USE_SECMEM is true, the returned passphrase is retruned in secure memory. The length of all these strings is limited; they need to fit in their encoded form into a standard Assuan line (i.e less then about 950 characters). All strings shall be UTF-8. */ gpg_error_t gnupg_get_passphrase (const char *cache_id, const char *err_msg, const char *prompt, const char *desc_msg, int repeat, int check_quality, int use_secmem, char **r_passphrase) { gpg_error_t err; char line[ASSUAN_LINELENGTH]; const char *arg1 = NULL; char *arg2 = NULL; char *arg3 = NULL; char *arg4 = NULL; membuf_t data; *r_passphrase = NULL; err = start_agent (); if (err) return err; /* Check that the gpg-agent understands the repeat option. */ if (assuan_transact (agent_ctx, "GETINFO cmd_has_option GET_PASSPHRASE repeat", NULL, NULL, NULL, NULL, NULL, NULL)) return gpg_error (GPG_ERR_NOT_SUPPORTED); arg1 = cache_id && *cache_id? cache_id:NULL; if (err_msg && *err_msg) if (!(arg2 = percent_plus_escape (err_msg))) goto no_mem; if (prompt && *prompt) if (!(arg3 = percent_plus_escape (prompt))) goto no_mem; if (desc_msg && *desc_msg) if (!(arg4 = percent_plus_escape (desc_msg))) goto no_mem; snprintf (line, DIM(line)-1, "GET_PASSPHRASE --data %s--repeat=%d -- %s %s %s %s", check_quality? "--check ":"", repeat, arg1? arg1:"X", arg2? arg2:"X", arg3? arg3:"X", arg4? arg4:"X"); line[DIM(line)-1] = 0; xfree (arg2); xfree (arg3); xfree (arg4); if (use_secmem) init_membuf_secure (&data, 64); else init_membuf (&data, 64); err = assuan_transact (agent_ctx, line, membuf_data_cb, &data, default_inq_cb, NULL, NULL, NULL); /* Older Pinentries return the old assuan error code for canceled which gets translated bt libassuan to GPG_ERR_ASS_CANCELED and not to the code for a user cancel. Fix this here. */ if (err && gpg_err_source (err) && gpg_err_code (err) == GPG_ERR_ASS_CANCELED) err = gpg_err_make (gpg_err_source (err), GPG_ERR_CANCELED); if (err) { void *p; size_t n; p = get_membuf (&data, &n); if (p) wipememory (p, n); xfree (p); } else { put_membuf (&data, "", 1); *r_passphrase = get_membuf (&data, NULL); if (!*r_passphrase) err = gpg_error_from_syserror (); } return err; no_mem: err = gpg_error_from_syserror (); xfree (arg2); xfree (arg3); xfree (arg4); return err; }
int main (int argc, char *argv[]) { int index; int c; int dflag = 0; char *cvalue = NULL; while ((c = getopt(argc, argv, "c:Dhv")) != -1) { switch (c) { case 'c': cvalue = optarg; break; case 'D': dflag = 1; break; case 'h': printf("Usage: %s [-c config_file] [-v] [-h]\n", argv[0]); return 0; case 'v': printf("%s v%s (revision %s) (%s)\n", APPLICATION_NAME, ROCNET_VERSION, ROCNET_REVISION, ROCNET_REVDATE); return 0; case '?': if (optopt == 'c') { fprintf(stderr, "-%c missing argument.\n", optopt); } else if (isprint (optopt)) { fprintf (stderr, "Unknown option `-%c'.\n", optopt); } else { fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); } return 1; default: abort(); } } for (index = optind; index < argc; index++) { printf("Non-option argument %s\n", argv[index]); } // setup logging now setlogmask(LOG_UPTO(LOG_DEBUG)); openlog(PROG_ID, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); syslog(LOG_NOTICE, "%s starting", PROG_ID); if (cvalue){ parse_file(cvalue); } else { parse_file(FILE_PATH); } if (setup_server() < 0) { syslog(LOG_ERR, "%s exiting [setup_server() failed]", PROG_ID); exit(EXIT_FAILURE); } // should we run as a daemon if (dflag) { if (daemon(0,0) < 0) { syslog(LOG_ERR, "error creating daemon: %s", strerror(errno)); exit(EXIT_FAILURE); } } else { print_config(); printf("-------\n"); printItemsList(); printf("\t\t-------\n"); } start_agent(); return 0; }
void Environment::load_argv(int argc, char** argv) { String* str = 0; Encoding* enc = Encoding::default_external(state); Array* os_ary = Array::create(state, argc); for(int i = 0; i < argc; i++) { str = String::create(state, argv[i]); str->encoding(state, enc); os_ary->set(state, i, str); } G(rubinius)->set_const(state, "OS_ARGV", os_ary); char buf[MAXPATHLEN]; str = String::create(state, getcwd(buf, MAXPATHLEN)); str->encoding(state, enc); G(rubinius)->set_const(state, "OS_STARTUP_DIR", str); str = String::create(state, argv[0]); str->encoding(state, enc); state->vm()->set_const("ARG0", str); Array* ary = Array::create(state, argc - 1); int which_arg = 0; bool skip_xflags = true; for(int i=1; i < argc; i++) { char* arg = argv[i]; if(strcmp(arg, "--") == 0) { skip_xflags = false; } else if(strncmp(arg, "-X", 2) == 0) { if(skip_xflags) continue; } else if(arg[1] != '-') { skip_xflags = false; } str = String::create(state, arg); str->taint(state); str->encoding(state, enc); ary->set(state, which_arg++, str); } state->vm()->set_const("ARGV", ary); // Now finish up with the config if(config.print_config > 1) { std::cout << "========= Configuration =========\n"; config.print(true); std::cout << "=================================\n"; } else if(config.print_config) { config.print(); } if(config.agent_start > 0) { // if port_ is 1, the user wants to use a randomly assigned local // port which will be written to the temp file for console to pick // up. int port = config.agent_start; if(port == 1) port = 0; start_agent(port); } state->shared().set_use_capi_lock(config.capi_lock); }
/* Locally starts (after service/win init) */ int local_start() { int debug_level; int accept_manager_commands = 0; char *cfg = DEFAULTCPATH; WSADATA wsaData; DWORD threadID; DWORD threadID2; /* Starting logr */ logr = (agent *)calloc(1, sizeof(agent)); if(!logr) { ErrorExit(MEM_ERROR, ARGV0); } logr->port = DEFAULT_SECURE; /* Getting debug level */ debug_level = getDefine_Int("windows","debug", 0, 2); while(debug_level != 0) { nowDebug(); debug_level--; } accept_manager_commands = getDefine_Int("logcollector", "remote_commands", 0, 1); /* Configuration file not present */ if(File_DateofChange(cfg) < 0) ErrorExit("%s: Configuration file '%s' not found",ARGV0,cfg); /* Starting Winsock */ if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { ErrorExit("%s: WSAStartup() failed", ARGV0); } /* Read agent config */ debug1("%s: DEBUG: Reading agent configuration.", ARGV0); if(ClientConf(cfg) < 0) { ErrorExit(CLIENT_ERROR,ARGV0); } if(logr->notify_time == 0) { logr->notify_time = NOTIFY_TIME; } if(logr->max_time_reconnect_try == 0 ) { logr->max_time_reconnect_try = NOTIFY_TIME * 3; } if(logr->max_time_reconnect_try <= logr->notify_time) { logr->max_time_reconnect_try = (logr->notify_time * 3); verbose("%s Max time to reconnect can't be less than notify_time(%d), using notify_time*3 (%d)",ARGV0,logr->notify_time,logr->max_time_reconnect_try); } verbose("%s Using notify time: %d and max time to reconnect: %d",ARGV0,logr->notify_time,logr->max_time_reconnect_try); /* Reading logcollector config file */ debug1("%s: DEBUG: Reading logcollector configuration.", ARGV0); if(LogCollectorConfig(cfg, accept_manager_commands) < 0) { ErrorExit(CONFIG_ERROR, ARGV0, cfg); } /* Checking auth keys */ if(!OS_CheckKeys()) { ErrorExit(AG_NOKEYS_EXIT, ARGV0); } /* If there is not file to monitor, create a clean entry * for the mark messages. */ if(logff == NULL) { os_calloc(2, sizeof(logreader), logff); logff[0].file = NULL; logff[0].ffile = NULL; logff[0].logformat = NULL; logff[0].fp = NULL; logff[1].file = NULL; logff[1].logformat = NULL; merror(NO_FILE, ARGV0); } /* Reading execd config. */ if(!WinExecd_Start()) { logr->execdq = -1; } /* Reading keys */ verbose(ENC_READ, ARGV0); OS_ReadKeys(&keys); OS_StartCounter(&keys); os_write_agent_info(keys.keyentries[0]->name, NULL, keys.keyentries[0]->id, NULL); /* Initial random numbers */ srandom(time(0)); random(); /* Socket connection */ logr->sock = -1; StartMQ(NULL, 0); /* Starting mutex */ debug1("%s: DEBUG: Creating thread mutex.", ARGV0); hMutex = CreateMutex(NULL, FALSE, NULL); if(hMutex == NULL) { ErrorExit("%s: Error creating mutex.", ARGV0); } /* Starting syscheck thread */ if(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)skthread, NULL, 0, (LPDWORD)&threadID) == NULL) { merror(THREAD_ERROR, ARGV0); } /* Checking if server is connected */ os_setwait(); start_agent(1); os_delwait(); /* Sending integrity message for agent configs */ intcheck_file(cfg, ""); intcheck_file(OSPATROL_DEFINES, ""); /* Starting receiver thread */ if(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)receiver_thread, NULL, 0, (LPDWORD)&threadID2) == NULL) { merror(THREAD_ERROR, ARGV0); } /* Sending agent information message */ send_win32_info(time(0)); /* Startting logcollector -- main process here */ LogCollectorStart(); WSACleanup(); return(0); }
/* Note: All strings shall be UTF-8. On success the caller needs to free the string stored at R_PASSPHRASE. On error NULL will be stored at R_PASSPHRASE and an appropriate fpf error code returned. */ gpg_error_t agent_get_passphrase (const char *cache_id, const char *err_msg, const char *prompt, const char *desc_msg, int repeat, int check, char **r_passphrase) { int rc; char line[ASSUAN_LINELENGTH]; char *arg1 = NULL; char *arg2 = NULL; char *arg3 = NULL; char *arg4 = NULL; membuf_t data; *r_passphrase = NULL; rc = start_agent (0); if (rc) return rc; /* Check that the gpg-agent understands the repeat option. */ if (assuan_transact (agent_ctx, "GETINFO cmd_has_option GET_PASSPHRASE repeat", NULL, NULL, NULL, NULL, NULL, NULL)) return gpg_error (GPG_ERR_NOT_SUPPORTED); if (cache_id && *cache_id) if (!(arg1 = percent_plus_escape (cache_id))) goto no_mem; if (err_msg && *err_msg) if (!(arg2 = percent_plus_escape (err_msg))) goto no_mem; if (prompt && *prompt) if (!(arg3 = percent_plus_escape (prompt))) goto no_mem; if (desc_msg && *desc_msg) if (!(arg4 = percent_plus_escape (desc_msg))) goto no_mem; snprintf (line, DIM(line)-1, "GET_PASSPHRASE --data --repeat=%d%s -- %s %s %s %s", repeat, check? " --check --qualitybar":"", arg1? arg1:"X", arg2? arg2:"X", arg3? arg3:"X", arg4? arg4:"X"); line[DIM(line)-1] = 0; xfree (arg1); xfree (arg2); xfree (arg3); xfree (arg4); init_membuf_secure (&data, 64); rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data, default_inq_cb, NULL, NULL, NULL); if (rc) xfree (get_membuf (&data, NULL)); else { put_membuf (&data, "", 1); *r_passphrase = get_membuf (&data, NULL); if (!*r_passphrase) rc = gpg_error_from_syserror (); } return rc; no_mem: rc = gpg_error_from_syserror (); xfree (arg1); xfree (arg2); xfree (arg3); xfree (arg4); return rc; }
void Environment::load_argv(int argc, char** argv) { Array* os_ary = Array::create(state, argc); for(int i = 0; i < argc; i++) { os_ary->set(state, i, String::create(state, argv[i])); } G(rubinius)->set_const(state, "OS_ARGV", os_ary); char buf[MAXPATHLEN]; G(rubinius)->set_const(state, "OS_STARTUP_DIR", String::create(state, getcwd(buf, MAXPATHLEN))); bool process_xflags = true; state->set_const("ARG0", String::create(state, argv[0])); Array* ary = Array::create(state, argc - 1); int which_arg = 0; for(int i=1; i < argc; i++) { char* arg = argv[i]; if(arg[0] != '-' || strcmp(arg, "--") == 0) { process_xflags = false; } if(process_xflags && strncmp(arg, "-X", 2) == 0) { config_parser.import_line(arg + 2); } else { ary->set(state, which_arg++, String::create(state, arg)->taint(state)); } } state->set_const("ARGV", ary); // Parse -X options from RBXOPT environment variable char* rbxopt = getenv("RBXOPT"); if(rbxopt) { char *e, *b = rbxopt = strdup(rbxopt); char *s = b + strlen(rbxopt); while(b < s) { while(*b && isspace(*b)) s++; e = b; while(*e && !isspace(*e)) e++; int len; if((len = e - b) > 0) { if(strncmp(b, "-X", 2) == 0) { *e = 0; config_parser.import_line(b + 2); } b = e + 1; } } free(rbxopt); } // Now finish up with the config config_parser.update_configuration(config); if(config.print_config > 1) { std::cout << "========= Configuration =========\n"; config.print(true); std::cout << "=================================\n"; } else if(config.print_config) { config.print(); } if(config.qa_port > 0) { // if port_ is 1, the user wants to use a randomly assigned local // port which will be written to the temp file for console to pick // up. int port = config.qa_port; if(port == 1) port = 0; start_agent(port); } if(config.report_path.set_p()) { // Test that we can actually use this path int fd = open(config.report_path, O_RDONLY | O_CREAT, 0666); if(!fd) { std::cerr << "Unable to use " << config.report_path << " for crash reports.\n"; std::cerr << "Unable to open path: " << strerror(errno) << "\n"; // Don't use the home dir path even, just use stderr report_path[0] = 0; } else { close(fd); unlink(config.report_path); strncpy(report_path, config.report_path, sizeof(report_path) - 1); } } }
void Environment::load_argv(int argc, char** argv) { String* str = 0; Encoding* enc = Encoding::default_external(state); Array* os_ary = Array::create(state, argc); for(int i = 0; i < argc; i++) { str = String::create(state, argv[i]); str->encoding(state, enc); os_ary->set(state, i, str); } G(rubinius)->set_const(state, "OS_ARGV", os_ary); char buf[MAXPATHLEN]; str = String::create(state, getcwd(buf, MAXPATHLEN)); str->encoding(state, enc); G(rubinius)->set_const(state, "OS_STARTUP_DIR", str); str = String::create(state, argv[0]); str->encoding(state, enc); state->vm()->set_const("ARG0", str); Array* ary = Array::create(state, argc - 1); int which_arg = 0; bool skip_xflags = true; for(int i=1; i < argc; i++) { char* arg = argv[i]; if(strcmp(arg, "--") == 0) { skip_xflags = false; } else if(strncmp(arg, "-X", 2) == 0) { if(skip_xflags) continue; } else if(arg[1] != '-') { skip_xflags = false; } str = String::create(state, arg); str->taint(state); str->encoding(state, enc); ary->set(state, which_arg++, str); } state->vm()->set_const("ARGV", ary); // Now finish up with the config if(config.print_config > 1) { std::cout << "========= Configuration =========\n"; config.print(true); std::cout << "=================================\n"; } else if(config.print_config) { config.print(); } if(config.agent_start > 0) { // if port_ is 1, the user wants to use a randomly assigned local // port which will be written to the temp file for console to pick // up. int port = config.agent_start; if(port == 1) port = 0; start_agent(port); } if(config.report_path.set_p()) { // Test that we can actually use this path int fd = open(config.report_path, O_RDONLY | O_CREAT, 0666); if(!fd) { std::cerr << "Unable to use " << config.report_path << " for crash reports.\n"; std::cerr << "Unable to open path: " << strerror(errno) << "\n"; // Don't use the home dir path even, just use stderr report_path[0] = 0; } else { close(fd); unlink(config.report_path); strncpy(report_path, config.report_path, sizeof(report_path) - 1); } } state->shared().set_use_capi_lock(config.capi_lock); }
/* AgentdStart v0.2, 2005/11/09 * Starts the agent daemon. */ void AgentdStart(char *dir, int uid, int gid, char *user, char *group) { int rc = 0; int pid = 0; int maxfd = 0; fd_set fdset; struct timeval fdtimeout; pid = getpid(); available_server = 0; /* Going Daemon */ if (!run_foreground) { nowDaemon(); goDaemonLight(); } /* Setting group ID */ if(Privsep_SetGroup(gid) < 0) ErrorExit(SETGID_ERROR, ARGV0, group); /* chrooting */ if(Privsep_Chroot(dir) < 0) ErrorExit(CHROOT_ERROR, ARGV0, dir); nowChroot(); if(Privsep_SetUser(uid) < 0) ErrorExit(SETUID_ERROR, ARGV0, user); /* Create the queue. In this case we are going to create * and read from it * Exit if fails. */ if((agt->m_queue = StartMQ(DEFAULTQUEUE, READ)) < 0) ErrorExit(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno)); maxfd = agt->m_queue; agt->sock = -1; /* Creating PID file */ if(CreatePID(ARGV0, getpid()) < 0) merror(PID_ERROR,ARGV0); /* Reading the private keys */ verbose(ENC_READ, ARGV0); OS_ReadKeys(&keys); OS_StartCounter(&keys); /* cmoraes : changed the following call to os_write_agent_info(keys.keyentries[0]->name, NULL, keys.keyentries[0]->id); */ os_write_agent_info(keys.keyentries[0]->name, NULL, keys.keyentries[0]->id, agt->profile); /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); /* Initial random numbers */ #ifdef __OpenBSD__ srandomdev(); #else srandom( time(0) + getpid()+ pid + getppid()); #endif random(); /* Connecting UDP */ rc = 0; while(rc < agt->rip_id) { verbose("%s: INFO: Server IP Address: %s", ARGV0, agt->rip[rc]); rc++; } /* Trying to connect to the server */ if(!connect_server(0)) { ErrorExit(UNABLE_CONN, ARGV0); } /* Setting max fd for select */ if(agt->sock > maxfd) { maxfd = agt->sock; } /* Connecting to the execd queue */ if(agt->execdq == 0) { if((agt->execdq = StartMQ(EXECQUEUE, WRITE)) < 0) { merror("%s: INFO: Unable to connect to the active response " "queue (disabled).", ARGV0); agt->execdq = -1; } } /* Trying to connect to server */ os_setwait(); start_agent(1); os_delwait(); /* Sending integrity message for agent configs */ intcheck_file(OSSECCONF, dir); intcheck_file(OSSEC_DEFINES, dir); /* Sending first notification */ run_notify(); /* Maxfd must be higher socket +1 */ maxfd++; /* monitor loop */ while(1) { /* Monitoring all available sockets from here */ FD_ZERO(&fdset); FD_SET(agt->sock, &fdset); FD_SET(agt->m_queue, &fdset); fdtimeout.tv_sec = 1; fdtimeout.tv_usec = 0; /* Continuously send notifications */ run_notify(); /* Wait with a timeout for any descriptor */ rc = select(maxfd, &fdset, NULL, NULL, &fdtimeout); if(rc == -1) { ErrorExit(SELECT_ERROR, ARGV0); } else if(rc == 0) { continue; } /* For the receiver */ if(FD_ISSET(agt->sock, &fdset)) { receive_msg(); } /* For the forwarder */ if(FD_ISSET(agt->m_queue, &fdset)) { EventForward(); } } }
/* Decrypt INDATA of length INDATALEN using the card identified by SERIALNO. Return the plaintext in a nwly allocated buffer stored at the address of R_BUF. Note, we currently support only RSA or more exactly algorithms taking one input data element. */ int agent_scd_pkdecrypt (const char *serialno, const unsigned char *indata, size_t indatalen, unsigned char **r_buf, size_t *r_buflen) { int rc; char line[ASSUAN_LINELENGTH]; membuf_t data; size_t len; struct cipher_parm_s ctparm; *r_buf = NULL; rc = start_agent (1); if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT || gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED) rc = 0; /* We check later. */ if (rc) return rc; /* FIXME: use secure memory where appropriate */ #if 0 if (indatalen*2 + 50 > DIM(line)) return gpg_error (GPG_ERR_GENERAL); #endif rc = select_openpgp (serialno); if (rc) return rc; #if 0 sprintf (line, "SCD SETDATA "); p = line + strlen (line); for (i=0; i < indatalen ; i++, p += 2 ) sprintf (p, "%02X", indata[i]); rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) return rc; #endif ctparm.ctx = agent_ctx; ctparm.ciphertext = indata; ctparm.ciphertextlen = indatalen; init_membuf (&data, 1024); snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno); line[DIM(line)-1] = 0; rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data, inq_ciphertext_cb, &ctparm, NULL, NULL); if (rc) { xfree (get_membuf (&data, &len)); } else { *r_buf = get_membuf (&data, r_buflen); if (!*r_buf) rc = gpg_error (GPG_ERR_ENOMEM); } status_sc_op_failure (rc); return rc; }
/* run_notify: Send periodically notification to server */ void run_notify() { char keep_alive_random[1024]; char tmp_msg[OS_SIZE_1024 +1]; char *uname; char *shared_files; os_md5 md5sum; keep_alive_random[0] = '\0'; time_t curr_time; curr_time = time(0); #ifndef ONEWAY /* Check if the server has responded */ if((curr_time - available_server) > (3*NOTIFY_TIME)) { /* If response is not available, set lock and * wait for it. */ verbose(SERVER_UNAV, ARGV0); os_setwait(); /* Send sync message */ start_agent(0); verbose(SERVER_UP, ARGV0); os_delwait(); } #endif /* Check if time has elapsed */ if((curr_time - g_saved_time) < (NOTIFY_TIME - 120)) { return; } g_saved_time = curr_time; debug1("%s: DEBUG: Sending agent notification.", ARGV0); /* Send the message. * Message is going to be the * uname\n checksum file\n checksum file\n */ /* Getting uname */ uname = getuname(); if(!uname) { merror(MEM_ERROR,ARGV0); return; } /* get shared files */ shared_files = getsharedfiles(); if(!shared_files) { shared_files = strdup("\0"); if(!shared_files) { free(uname); merror(MEM_ERROR,ARGV0); return; } } rand_keepalive_str2(keep_alive_random, 700); /* creating message */ if((File_DateofChange(AGENTCONFIGINT) > 0 ) && (OS_MD5_File(AGENTCONFIGINT, md5sum) == 0)) { snprintf(tmp_msg, OS_SIZE_1024, "#!-%s / %s\n%s\n%s", uname, md5sum, shared_files, keep_alive_random); } else { snprintf(tmp_msg, OS_SIZE_1024, "#!-%s\n%s\n%s", uname, shared_files, keep_alive_random); } /* Sending status message */ send_msg(0, tmp_msg); free(uname); free(shared_files); return; }
/* * Logger helper app [only for non-unix systems] */ INTERNAL void logger(char *pgm, int argc, char **argv) { char *logserver; char *cmd; char args[AGENTD_PATHLEN]; int id, nc; int pid; int ok, help; int i; int rc; ok = 1; help = 0; Verbose = 0; while (argc && *argv[0] == '-') { char *opt; opt = argv[0] + 1; ++argv; --argc; if (substr(opt, "help")) ++help; else if (substr(opt, "debug")) ++Debug; else if (substr(opt, "nodebug")) Debug = 0; else if (substr(opt, "verbose")) Verbose = 1; else if (substr(opt, "quiet")) Verbose = 0; else if (substr(opt, "wd")) { if (argc < 1) { fprintf(stderr, "%s: missing argument to -%s\n", pgm, opt); ok = 0; break; } WorkDir = argv[0]; ++argv; --argc; } else if (substr(opt, "bin")) { if (argc < 1) { fprintf(stderr, "%s: missing argument to -%s\n", pgm, opt); ok = 0; break; } strcpy(ExecPath, argv[0]); ++argv; --argc; } else { fprintf(stderr, "%s: ignoring argument -%s\n", pgm, opt); help = 1; ok = 0; } } if (!ok || argc == 0) { logger_usage(pgm, help); exit(!help); } if (argc < 2) { fprintf(stderr, "usage: %s logserver cmd [args]\n", pgm); exit(4); } logserver = argv[0]; ++argv; --argc; cmd = argv[0]; ++argv; --argc; args[0] = '\0'; while (argc) { strcat(args, " "); strcat(args, argv[0]); ++argv; --argc; } /* Initialize agent control structures */ for (i = 0; i < MAX_AGENT; ++i) { Agent[i].pid = 0; Agent[i].status = AGENTD_AGENT_FREE; } event_verbose(Verbose); event_tunnel_enable(0); agentd_init(); siginit(); /* deal with signals */ id = event_join(logserver, &nc); if (id <= 0) { fprintf(stderr, "%s: couldn't join server %s\n", pgm, logserver); exit(4); } /* * N.B. For the moment disable the reading of all events * if we need to process incoming events, for some reason, we * should launch a separate thread, similar to the stdout/err * "reader" threads that get started in "start_agent". * Note that start_agent does not return until the subproccess, * i.e. the agent, terminates */ event_select_type(0, ET_MIN, ET_MAX); /*** No, not even these event_select_type(1, ET_AGENTD_MIN, ET_AGENTD_MAX); ***/ event_receive_enable(0); event_flush(1); event_register(LOGGERCLASS, LOGGERSPEC, cmd); rc = start_agent(NULL, cmd, args, &pid); event_leave(); exit(rc); }