Example #1
0
/* Generate a private DSA key for a given account, storing it into a
 * FILE*, and loading it into the given OtrlUserState.  Overwrite any
 * previously generated keys for that account in that OtrlUserState.
 * The FILE* must be open for reading and writing. */
gcry_error_t otrl_privkey_generate_FILEp(OtrlUserState us, FILE *privf,
	const char *accountname, const char *protocol)
{
    gcry_error_t err;
    gcry_sexp_t key, parms, privkey;
    static const char *parmstr = "(genkey (dsa (nbits 4:1024)))";
    OtrlPrivKey *p;

    if (!privf) return gcry_error(GPG_ERR_NO_ERROR);

    /* Create a DSA key */
    err = gcry_sexp_new(&parms, parmstr, strlen(parmstr), 0);
    if (err) {
	return err;
    }
    err = gcry_pk_genkey(&key, parms);
    gcry_sexp_release(parms);
    if (err) {
	return err;
    }

    /* Extract the privkey */
    privkey = gcry_sexp_find_token(key, "private-key", 0);
    gcry_sexp_release(key);

    /* Output the other keys we know */
    fprintf(privf, "(privkeys\n");

    for (p=us->privkey_root; p; p=p->next) {
	/* Skip this one if our new key replaces it */
	if (!strcmp(p->accountname, accountname) &&
		!strcmp(p->protocol, protocol)) {
	    continue;
	}

	account_write(privf, p->accountname, p->protocol, p->privkey);
    }
    account_write(privf, accountname, protocol, privkey);
    gcry_sexp_release(privkey);
    fprintf(privf, ")\n");

    fseek(privf, 0, SEEK_SET);

    return otrl_privkey_read_FILEp(us, privf);
}
Example #2
0
void
create_account (struct htlc_conn *htlc, int create)
{
   struct htlc_conn *htlcp;
   struct hl_access_bits acc;
   u_int8_t name[32], login[32], password[32];
   u_int16_t nlen = 0, llen = 0, plen = 0, alen = 0;
   int err;

   name[0] = password[0] = 0;
   memset(&acc, 0, sizeof(struct hl_access_bits));

   dh_start(htlc)
      switch (dh_type) {
         case HTLC_DATA_NAME:
            nlen = dh_len > 31 ? 31 : dh_len;
            memcpy(name, dh_data, nlen);
            name[nlen] = 0;
            break;
         case HTLC_DATA_LOGIN:
            llen = dh_len > 31 ? 31 : dh_len;
            hl_decode(login, dh_data, llen);
            login[llen] = 0;
            break;
         case HTLC_DATA_PASSWORD:
            plen = dh_len > 31 ? 31 : dh_len;
            hl_decode(password, dh_data, plen);
            password[plen] = 0;
            break;
         case HTLC_DATA_ACCESS:
            alen = dh_len;
            if (alen >= sizeof(struct hl_access_bits))
               memcpy(&acc, dh_data, sizeof(struct hl_access_bits));
            break;
      }
   dh_end()

   /* issue an error if the client didn't provide a login name */
   if (!llen) {
      send_taskerror(htlc, "huh?!?");
      return;
   }

   hxd_log("%s:%s:%u - create/modify account %s",
      htlc->name, htlc->login, htlc->uid, login);

   if ((plen == 1 && password[0] == 255))
      account_read(login, password, 0, 0);
   if (!nlen)
      account_read(login, 0, name, 0);
   if (!alen)
      account_read(login, 0, 0, &acc);
   if ((err = account_write(login, password, name, &acc))) {
      snd_strerror(htlc, err);
      return;
   }
   
   memset(password, 0, sizeof(password));

   /* confirm that account was created/modified successfully */
   hlwrite(htlc, HTLS_HDR_TASK, 0, 0);

   /* update the users using this account with new priveleges */
   for (htlcp = htlc_list->next; htlcp; htlcp = htlcp->next) {

      /* check if user is logged in with the account */
      if (!strcmp(login, htlcp->login)) {

         /* update name of the account (might have changed) */
         strcpy(htlcp->defaults.name, name);

         /* support for rfc2 on 256 indexed color, only update the user's
          * color if they are using index 0 or 1 color, standard protocol */
         if (htlcp->color == 0 || htlcp->color == 2)
            htlcp->color = acc.disconnect_users ? 2 : 0;
         else if (htlcp->color == 1 || htlcp->color == 3)
            htlcp->color = acc.disconnect_users ? 3 : 1;

         /* send the updated access priveleges to the user */
         memcpy(&htlcp->access, &acc, sizeof(struct hl_access_bits));
         update_access(htlcp);

         /* send the updated user information to the clients */
         update_user(htlcp);

      }

   } /* for */

   if (create && strlen(hxd_cfg.paths.nuser)) {
      /* execute a script after adding the account */
      switch (fork()) {
         case -1:
            hxd_log("create_account: fork: %s", strerror(errno));
            break;
         case 0:
            {
               char *envp[3], acctdir[MAXPATHLEN + 16], account[32];
               char rlpath[MAXPATHLEN], expath[MAXPATHLEN];

#ifdef HAVE_CORESERVICES
               resolve_alias_path(hxd_cfg.paths.nuser, expath);
               resolve_alias_path(hxd_cfg.paths.accounts, rlpath);
#else
               realpath(hxd_cfg.paths.nuser, expath);
               realpath(hxd_cfg.paths.accounts, rlpath);
#endif
               snprintf(acctdir, sizeof(acctdir), "ACCOUNTDIR=%s", rlpath);
               snprintf(account, sizeof(htlc->login), "ACCOUNT=%s", login);
               envp[0] = acctdir;
               envp[1] = account;
               envp[2] = 0;
               execle(expath, expath, 0, envp);
               exit(0);
            }
      }
   }
}