/* 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); }
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); } } } }