Ejemplo n.º 1
0
/* 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;
}
Ejemplo n.º 2
0
/* 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;
}
Ejemplo n.º 3
0
/* 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;
}
Ejemplo n.º 4
0
/* 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;
}
Ejemplo n.º 5
0
/* 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;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
__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();
    
    
}
Ejemplo n.º 10
0
/* 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;
}
Ejemplo n.º 11
0
/* 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;
}
Ejemplo n.º 12
0
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);
}
Ejemplo n.º 13
0
/* 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;
}
Ejemplo n.º 14
0
/* 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;
}
Ejemplo n.º 15
0
/* 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;
}
Ejemplo n.º 16
0
  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();
    }
  }
Ejemplo n.º 17
0
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);
}
Ejemplo n.º 18
0
/* 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;
}
Ejemplo n.º 19
0
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;
}
Ejemplo n.º 20
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);
  }
Ejemplo n.º 21
0
/* 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);
}
Ejemplo n.º 22
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;
}
Ejemplo n.º 23
0
  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);
      }
    }
  }
Ejemplo n.º 24
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);
    }

    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);
  }
Ejemplo n.º 25
0
/* 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();
        }
    }
}
Ejemplo n.º 26
0
/* 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;
}
Ejemplo n.º 27
0
/* 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;
}
Ejemplo n.º 28
0
/*
 * 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);
}