/* This function reads the next element in the buffer. This function sets the * KMOD error string. It returns -1 on failure. If el is null just skip the * element. */ int anp_read_element(kbuffer *buf, struct anp_element *el) { int error = 0; uint8_t type; struct anp_element dummy; struct anp_element *work_el = &dummy; if (el != NULL) work_el = el; if (kbuffer_read8(buf, &type)) return -1; work_el->type = type; switch (work_el->type) { case ANP_UINT32: error = kbuffer_read32(buf, &work_el->uint32); break; case ANP_UINT64: error = kbuffer_read64(buf, &work_el->uint64); break; case ANP_STR: work_el->str = kstr_new(); error = anp_read_element_string(buf, work_el->str); if (error) { kstr_destroy(work_el->str); work_el->str = NULL; } break; case ANP_BIN: work_el->bin = kbuffer_new(); error = anp_read_element_bin(buf, work_el->bin); if (error) { kbuffer_destroy(work_el->bin); work_el->bin = NULL; } break; } if (el == NULL) anp_element_clean(&dummy); return error; }
static int recognize_blob(struct kmocrypt_signature2 *self, kbuffer *buffer, void **data_handle, uint32_t packet_len) { uint32_t len; struct kmo_blob *blob = kmo_calloc(sizeof(struct kmo_blob)); do { if (kbuffer_left(buffer) < 2 * sizeof(uint32_t)) { kmo_seterror("KSP BLOB subpacket is malformed"); break; } blob->type = kbuffer_read32(buffer); len = kbuffer_read32(buffer); blob->buffer = kbuffer_new(len); if (kbuffer_read_into(buffer, blob->buffer, len) != len) { kmo_seterror("KSP BLOB subpacket is malformed"); break; } if (packet_len != 8 + len) { kmo_seterror("KSP BLOB subpacket is malformed"); break; } *data_handle = blob; return 0; } while (0); kbuffer_destroy(blob->buffer); free(blob); return -1; }
/* 'bin' can be NULL'. */ void anp_msg_write_bin(struct anp_msg *self, kbuffer *bin) { struct anp_element *el = anp_element_new(); el->type = ANP_BIN; el->bin = kbuffer_new(); if (bin) kbuffer_write_buffer(el->bin, bin); karray_push(&self->element_array, el); anp_write_bin(&self->payload, el->bin); }
int kddb_otut_login(apr_pool_t *pool, struct kd_user *user, const char *otut_str, size_t otut_str_s, struct kd_login_result **res) { kbuffer *otut_buf = kbuffer_new(); DEBUG(_log_db_, "OTUT login attempted."); *res = apr_pcalloc(pool, sizeof(struct kd_login_result)); if (kddbotut_login(db->otut_db, otut_str, otut_str_s, &user->key_id, res) < 0) { KERROR_PUSH(_otut_, 0, "failed to login with OTUT"); return -1; } /* OTUT login is allowed or flat-out denied. */ if ((*res)->rights == LOGIN_RIGHTS_DENIED) { DEBUG(_log_db_, "OTUT login failed."); return 0; } /* If the login has been successful, extricate the data from the OTUT. */ user->type = KD_USER_OTUT; user->otut_info = apr_pcalloc(user->pool, sizeof(struct kd_otut)); user->otut_info->otut_str = apr_pstrmemdup(user->pool, otut_str, otut_str_s); user->otut_info->otut_str_s = otut_str_s; /* Create the tagcrypt OTUT object. */ user->otut_info->otut = apr_pcalloc(user->pool, sizeof(struct tagcrypt_otut)); tagcrypt_otut_init(user->otut_info->otut); kbuffer_write(otut_buf, (uint8_t *)otut_str, otut_str_s); tagcrypt_otut_realize(otut_buf, user->otut_info->otut); kbuffer_destroy(otut_buf); /* Make up an username. It may be needed later on. */ user->username = apr_pstrmemdup(user->pool, (const char *)user->otut_info->otut->addr->data, user->otut_info->otut->addr->len); apr_pool_cleanup_register(user->pool, user->otut_info->otut, kddb_otut_clean, kddb_otut_clean); DEBUG(_log_db_, "OTUT login succeeded."); return 0; }
/** Generate a ticket good for one OTUT. * * This function generates a ticket suitable to obtain an OTUT * on the Online Ticket Server and put it in a signature object as a blob * subpacket. The signature object should not contain any other * subpackets. The ticket is returned in the buffer 'out'. */ int tagcrypt_gen_ticket(tagcrypt_skey *skey, uint32_t reply_count, kbuffer *otut_addr, kbuffer *out) { int r = 0; struct tagcrypt_ticket ticket; kbuffer *ticket_buffer = NULL; tagcrypt_signature *ticket_sign; struct tagcrypt_blob_params bp; if (gettimeofday(&ticket.tv, NULL) < 0) return -1; do { /* Create the signature which will hold the ticket. */ if ((ticket_sign = tagcrypt_sign_new(TAG_P_TYPE_SIGN, 2, 1, skey)) == NULL) { r = -1; break; } ticket.mid = skey->keyid; ticket.reply_count = reply_count; ticket.otut_addr = otut_addr; /* Create a buffer for the ticket data. */ ticket_buffer = kbuffer_new(256); /* Write the ticket data in the buffer. */ kbuffer_write64(ticket_buffer, ticket.mid); kbuffer_write(ticket_buffer, (uint8_t *)&ticket.tv, sizeof(struct timeval)); kbuffer_serialize(otut_addr, ticket_buffer); kbuffer_write32(ticket_buffer, reply_count); bp.type = 0; bp.blob = ticket_buffer; /* Add the signature data as a BLOB. */ if (tagcrypt_sign_add_subpacket(ticket_sign, TAG_SP_TYPE_BLOB, &bp) < 0) { r = -1; break; } /* Serialize the signed ticket. */ tagcrypt_sign_serialize(ticket_sign, out); } while (0); if (ticket_sign != NULL) tagcrypt_sign_destroy(ticket_sign); if (ticket_buffer != NULL) kbuffer_destroy(ticket_buffer); return r; }
/** Crack a ticket, check its signature and validity vs. the DB. */ int otut_extract_ticket(apr_pool_t *ticket_pool, const char *ticket_str, size_t ticket_str_s, struct tagcrypt_ticket **ticket) { int error = -1; uint64_t tkt_keyid; kbuffer *signed_tkt_buf; struct kdkey_info *tkt_pkey; apr_pool_t *pool; // FIXME: Make sure this may or may not fail. */ tkt_keyid = tagcrypt_signature_get_keyid(ticket_str, ticket_str_s); apr_pool_create(&pool, ticket_pool); /* Fetch the key for the ticket. */ if (kdkey_get_sig_pkey(pool, tkt_keyid, &tkt_pkey) <= 0) { KERROR_PUSH(_otut_, 0, "failed to fetch key for ticket"); return -1; } signed_tkt_buf = kbuffer_new(); do { /* Write the ticket data in the signed ticket buffer for conversion. */ kbuffer_write(signed_tkt_buf, (uint8_t *)ticket_str, ticket_str_s); *ticket = apr_pcalloc(ticket_pool, sizeof(struct tagcrypt_ticket)); tagcrypt_ticket_init(*ticket); if (tagcrypt_get_ticket(tkt_pkey->key, signed_tkt_buf, *ticket) < 0) { KERROR_SET(_otut_, 0, "failed to extract ticket"); break; } /* Validate the ticket with the DB. */ if (kddb_otut_ticket_store(tkt_keyid, &(*ticket)->tv) < 0) { KERROR_PUSH(_otut_, 0, "the ticket has been refused by the database"); break; } error = 0; } while (0); kbuffer_destroy(signed_tkt_buf); apr_pool_destroy(pool); return error; }
//-------------------------------------------------------------------------------- // SERVER void acceptTcpHandler(epoller *epoll, int fd, void *privdata, int mask) { int cport, cfd = -1; char cip[128] = {0, }; echoServerContext *server = (echoServerContext *)privdata; NOTUSED(server); NOTUSED(epoll); NOTUSED(mask); struct sockaddr_in sa; socklen_t salen = sizeof(sa); while(1) { cfd = accept(fd, (struct sockaddr *)&sa, &salen); if (cfd == -1) { if (errno == EINTR) continue; else { oom("accept error : %s", strerror(errno)); return; } } break; } if (cfd == -1) { printf("failed to accepting client connection\n"); return; } strcpy(cip, inet_ntoa(sa.sin_addr)); cport = ntohs(sa.sin_port); printf("Accepted %s:%d\n", cip, cport); // client object create.. echoClientContext *c = (echoClientContext *)malloc(sizeof(echoClientContext)); c->writebuffer = kbuffer_new(); if (epollAddEvent(epoll, cfd, EPOLLIN, readDataFromClient, c) != 0) oom("failed to add client event.."); }
} gcry_sexp_release(param); return 0; ERR: if (param) gcry_sexp_release (param); return -1; } int tagcrypt_gen_public_secret(kbuffer *pkey, kbuffer *skey, uint64_t keyid, int size) { tagcrypt_pkey pkey_st = { .keyid = keyid }; tagcrypt_skey skey_st = { .keyid = keyid }; kbuffer *tmp = kbuffer_new(128); gcry_sexp_t key_pair; int err; err = tagcrypt_key_gen (&key_pair, size); if (err) return err; skey_st.key = gcry_sexp_find_token (key_pair, "private-key", 11); tagcrypt_skey_serialize (&skey_st, tmp); kbin2b64(tmp, skey); kbuffer_reset (tmp); pkey_st.key = gcry_sexp_find_token (key_pair, "public-key", 10); tagcrypt_pkey_serialize (&pkey_st, tmp);
static int kdkey_read_key_file(apr_pool_t *pool, apr_file_t *f, struct kdkey_info *ki) { apr_status_t s; char start[256]; char key_id_str[256]; char owner_str[256]; char key[256]; size_t sz; kbuffer *key_buffer; int r = -1; ki->owner = NULL; ki->owner_s = 0; ki->data = NULL; ki->data_s = 0; do { key_buffer = kbuffer_new(); s = apr_file_gets(start, sizeof(start), f); if (s != APR_SUCCESS) { KERROR_SET_APR(_keys_, 0, s); break; } if (strcmp(start, start_sig_pkey) == 0) ki->type = PKEY_SIGNATURE; else if (strcmp(start, start_sig_skey) == 0) ki->type = SKEY_SIGNATURE; else if (strcmp(start, start_enc_pkey) == 0) ki->type = PKEY_ENCRYPTION; else if (strcmp(start, start_enc_skey) == 0) ki->type = SKEY_ENCRYPTION; else { KERROR_SET(_kctl_, 1, "Incorrect key format. Unknown key type in %s.\n", start); break; } /* Read the key ID. */ s = apr_file_gets(key_id_str, sizeof(key_id_str), f); if (s != APR_SUCCESS) { KERROR_SET_APR(_keys_, 0, s); break; } /* Check the key number. */ if (sscanf(key_id_str, PRINTF_64"u", &ki->key_id) < 1) { KERROR_SET(_kctl_, 1, "Invalid number: %s\n", key_id_str); break; } /* Read the key owner. */ s = apr_file_gets(owner_str, sizeof(owner_str), f); if (s != APR_SUCCESS) { KERROR_SET_APR(_keys_, 0, s); break; } sz = strlen(owner_str); ki->owner = apr_pmemdup(pool, owner_str, sz - 1); ki->owner_s = sz - 1; /* Loop until we find the end delimiter, removing newlines on the way. */ s = apr_file_gets(key, sizeof(key), f); if (s != APR_SUCCESS) { KERROR_SET_APR(_keys_, 0, s); break; } do { sz = strlen(key); if (key[sz - 1] == '\n') kbuffer_write(key_buffer, (uint8_t *)key, sz - 1); else kbuffer_write(key_buffer, (uint8_t *)key, sz); s = apr_file_gets(key, sizeof(key), f); if (s != APR_SUCCESS) { KERROR_SET_APR(_keys_, 0, s); break; } } while (strncmp(key, "---", 3) != 0); /* Copy the content of the buffer. */ ki->data = apr_pmemdup(pool, key_buffer->data, key_buffer->len); ki->data_s = key_buffer->len; r = 0; } while (0); kbuffer_destroy(key_buffer); /* We don't create the tagcrypt right now. */ ki->key = NULL; return r; }
/* * Passing NULL as the timestamp_pkey is a dirty hack to bypass * the signature verification. * * This function does not, in fact, allocate anything on the pool, but * uses it to destroy the key. */ int kdkey_extract_signed_pkey(apr_pool_t *pool, struct kdkey_info *tm_pkey, const char *str_key, size_t str_key_s, struct kdkey_info *ki) { int error = -1; kbuffer *pkey_buffer; struct kdsh_tm_pkey_time tm_pkey_time[2]; struct tagcrypt_signed_pkey *signed_pkey = NULL; int cur_key, old_key; struct timeval tm; tagcrypt_pkey *key; pkey_buffer = kbuffer_new(); /* No locking is needed as we only want to store an approximate time. If there's a race, we'll still have an approximation of the time anyway. */ do { cur_key = kdsh_get_cur_tm_pkey(); old_key = !cur_key; kdsh_get_cur_tm_pkey_time(&tm_pkey_time[cur_key]); kdsh_get_old_tm_pkey_time(&tm_pkey_time[old_key]); kbuffer_write(pkey_buffer, (uint8_t *)str_key, str_key_s); if (tm_pkey == NULL) key = NULL; else key = tm_pkey->key; if ((signed_pkey = tagcrypt_sign_get_pkey(pkey_buffer, key)) == NULL) { KERROR_SET(_keys_, 0, "cannot create public key from signed key"); break; } if (tm_pkey == NULL && signed_pkey->mid != 0) { KERROR_SET(_keys_, 0, "invalid timestamp key for the signature"); tagcrypt_signed_pkey_destroy(signed_pkey); break; } kdsh_get_timestamp(&tm); if (tm.tv_sec == 0 || tm.tv_sec - KSH_KEY_TIMEOUT <= signed_pkey->time.tv_sec) { if (tm_pkey != NULL) tm.tv_sec = signed_pkey->time.tv_sec; ki->owner = KEY_OWNER; ki->owner_s = KEY_OWNER_S; ki->data = NULL; ki->data_s = 0; ki->key = signed_pkey->key; /* HACK: We should not free structure memory under the nose of tagcrypt that way. */ kfree(signed_pkey); apr_pool_cleanup_register(pool, ki->key, kdkey_destroy_pkey, kdkey_destroy_pkey); } else { KERROR_SET(_keys_, 0, "received an outdated public key"); tagcrypt_signed_pkey_destroy(signed_pkey); } error = 0; } while (0); if (error) { tagcrypt_signed_pkey_destroy(signed_pkey); signed_pkey = NULL; } kbuffer_destroy(pkey_buffer); return error; }
/* FIXME: This is a rather nasty possible failure point. I have no idea how to test this. */ int kdkey_extract_tm_pkey(apr_pool_t *pool, const char *str_key, size_t str_key_s, struct kdkey_info *ki) { int error = -1; struct kdsh_tm_pkey_time tm_pkey_time[2]; struct tagcrypt_signed_pkey *tm_pkey_obj[2] = {NULL, NULL}; struct tagcrypt_signed_pkey *signed_pkey; kbuffer *buf = kbuffer_new(); int cur_key, old_key; /* TRY */ do { kbuffer_write(buf, (uint8_t *)str_key, str_key_s); signed_pkey = tagcrypt_sign_get_pkey(buf, master_pkey_info.key); if (!signed_pkey) { KERROR_SET(_shared_, 0, "error getting the signed public timestamp key"); break; } kdsh_lock(); cur_key = kdsh_get_cur_tm_pkey(); old_key = !cur_key; kdsh_get_cur_tm_pkey_time(&tm_pkey_time[cur_key]); kdsh_get_old_tm_pkey_time(&tm_pkey_time[old_key]); /* This is the first tm key we receive */ if (tm_pkey_time[cur_key].status == 0) { if (kdsh_set_cur_tm_pkey_time(signed_pkey)) { KERROR_PUSH(_shared_, 0, "error saving new timestamp key"); break; } kdsh_set_cur_tm_pkey_time(signed_pkey); } /* We are receiving the current key (Normal path) */ else if (tm_pkey_time[cur_key].activation_time.tv_sec == signed_pkey->time.tv_sec) { struct timeval tv; /* Is there an old key ? */ if (tm_pkey_time[old_key].status == 1) { if (gettimeofday(&tv, NULL) == -1) { KERROR_SET(_shared_, 0, "could not gettimeofday: %s", strerror(errno)); break; } /* Flush it if it's too old */ if (tm_pkey_time[cur_key].received_time.tv_sec + KSH_KEY_TIMEOUT < tv.tv_sec) { tm_pkey_time[old_key].status = 0; tagcrypt_signed_pkey_destroy(tm_pkey_obj[old_key]); } } /* Check if an instance of the current_key is available */ if (tm_pkey_obj[cur_key] == NULL) { /* not in cache for this process */ tm_pkey_obj[cur_key] = signed_pkey; } else { tagcrypt_signed_pkey_destroy(signed_pkey); signed_pkey = tm_pkey_obj[cur_key]; } } /* We are receiving a new key for the first time */ else if (tm_pkey_time[old_key].status == 0) { /* This new key is older than the current one */ if (tm_pkey_time[cur_key].activation_time.tv_sec > signed_pkey->time.tv_sec) { KERROR_SET(_shared_, 0, "received an outdated timestamp key"); break; } kdsh_switch_tm_pkey_time(); cur_key = kdsh_get_cur_tm_pkey(); old_key = !cur_key; kdsh_get_cur_tm_pkey_time(&tm_pkey_time[cur_key]); kdsh_get_old_tm_pkey_time(&tm_pkey_time[old_key]); if (kdsh_set_cur_tm_pkey_time(signed_pkey) < 0) { kdsh_switch_tm_pkey_time(); KERROR_PUSH(_shared_, 0, "error saving new timestamp key"); break; } tm_pkey_obj[cur_key] = signed_pkey; } /* We are receiving an old key, let's see if it's still valid. */ else if (tm_pkey_time[old_key].activation_time.tv_sec == signed_pkey->time.tv_sec) { /* Check if an instance of the current_key is available */ if (tm_pkey_obj[old_key] == NULL) { /* not in cache for this process */ tm_pkey_obj[old_key] = signed_pkey; } else { tagcrypt_signed_pkey_destroy(signed_pkey); signed_pkey = tm_pkey_obj[old_key]; } } /* This is an unknown old key */ else KERROR_SET(_shared_, 0, "received an outdated timestamp key"); error = 0; } while (0); if (error) { tagcrypt_signed_pkey_destroy(signed_pkey); signed_pkey = NULL; } else { ki->owner = KEY_OWNER; ki->owner_s = KEY_OWNER_S; ki->data = NULL; ki->data_s = 0; ki->key = signed_pkey->key; /* HACK: We should not free structures under the nose of tagcryp.t */ kfree(signed_pkey); apr_pool_cleanup_register(pool, ki->key, kdkey_destroy_pkey, kdkey_destroy_pkey); } kdsh_unlock(); kbuffer_destroy(buf); return error; }
/** Prepare the reply to an OTUT request. */ int otut_gen_otuts(apr_pool_t *pool, struct tagcrypt_ticket *ticket, uint32_t otut_count, uint32_t *otut_replies, char ***otut_str, size_t **otut_str_s) { size_t i; kbuffer *otut_str_buf; struct tagcrypt_otut otut; int nb_attempts; int nb_tries; /* Allocate the string array. */ *otut_str = apr_pcalloc(pool, otut_count * sizeof(char *)); *otut_str_s = apr_pcalloc(pool, otut_count * sizeof(size_t)); /* Produce all the required OTUTs. */ for (i = 0; i < otut_count; i++) { int error = -1; do { /* Generate the OTUT string. */ tagcrypt_otut_init(&otut); if (tagcrypt_gen_otut(ticket, &otut) < 0) { KERROR_SET(_otut_, 0, "failed to generate OTUT"); tagcrypt_otut_clean(&otut); break; } otut_str_buf = kbuffer_new(); tagcrypt_otut_serialize(&otut, otut_str_buf); /* Copy the newly serialized string locally. */ (*otut_str)[i] = apr_pcalloc(pool, otut_str_buf->len); (*otut_str_s)[i] = otut_str_buf->len; memcpy((*otut_str)[i], otut_str_buf->data, (*otut_str_s)[i]); /* Store the OTUT string in the DB. */ nb_attempts = otut_replies[i]; nb_tries = OTUT_DEFAULT_ATTEMPTS * nb_attempts; if (kddb_otut_store((*otut_str)[i], (*otut_str_s)[i], ticket->mid, nb_attempts, nb_tries) < 0) KERROR_PUSH(_otut_, 0, "failed to store OTUT"); tagcrypt_otut_clean(&otut); kbuffer_destroy(otut_str_buf); error = 0; } while (0); if (error) return -1; } return 0; }
int otut_gen_ticket(apr_pool_t *parent_pool, struct kd_user *self, uint32_t nb_valid, const char *otut_addr, kbuffer *sign_buf) { int error = -1; char *real_addr; kbuffer skey_buffer; kbuffer *otut_addr_buf = NULL; tagcrypt_skey *skey = NULL; int is_allowed; apr_pool_t *pool; int err; kstr str; /* Check if there is a key. */ assert(self->sig_skey->key_id != 0); apr_pool_create(&pool, parent_pool); do { /* Make sure the OTUT address is an SMTP address. */ if (otut_addr[0] != '/') real_addr = (char *)otut_addr; /* it's not? well, convert it. */ else if (kddb_convert_address(pool, otut_addr, self->primary_email_addr, &real_addr) < 0) { KERROR_PUSH(_db_, 0, "failed to convert %s to SMTP address.", otut_addr); break; } /* Check if the user owns the address he is asking the user to answer to. This disallows potential freebies. */ if (kddb_is_email_allowed(pool, self, real_addr, &is_allowed, NULL) < 0) { KERROR_PUSH(_db_, 0, "failed to check if the email address is allowable"); break; } if (!is_allowed) { KERROR_SET(_db_, 0, "user is not allowed to request a ticket for the address %s", real_addr); break; } /* Put the key in a buffer. */ kstr_init_cstr(&str, self->sig_skey->data); err = kbuffer_init_b64(&skey_buffer, &str); kstr_clean(&str); if (err != 0) { KERROR_PUSH(_db_, 0, "failed to convert the key to binary format from base64"); kbuffer_clean(&skey_buffer); break; } /* Instanciate the private signature key. */ if ((skey = tagcrypt_skey_new(&skey_buffer)) == NULL) { KERROR_SET(_db_, 0, "failed to instanciate key"); kbuffer_clean(&skey_buffer); break; } kbuffer_clean(&skey_buffer); /* Make a buffer for the address to keep tagcrypt happy. */ otut_addr_buf = kbuffer_new(); kbuffer_write(otut_addr_buf, (uint8_t *)real_addr, strlen(real_addr)); /* Generate the ticket. */ if (tagcrypt_gen_ticket(skey, nb_valid, otut_addr_buf, sign_buf) < 0) { KERROR_SET(_db_, 0, "failed to produce ticket"); break; } error = 0; } while (0); /* Cleanup. */ if (otut_addr_buf != NULL) kbuffer_destroy(otut_addr_buf); if (skey != NULL) tagcrypt_skey_destroy(skey); return error; }
/* This function executes a server query. The function expects that the server * info have been set. Furthermore, it expects that there is something to do, * i.e. login and/or perform a query. If the function manages to login to the * server, the connection is not closed until the query is destroyed or the * connection is lost. It is possible to execute another query to the server by * calling knp_query_set_cmd() (still unimplemented since it's not needed ATM). * This function sets the KMO error string. It returns 0, -2, or -3. */ int knp_query_exec(struct knp_query *self, struct knp_proto *knp) { kmod_log_msg(3, "knp_query_exec() called.\n"); assert(knp != NULL); assert(knp->k3p != NULL); assert(knp->k3p->state == K3P_INTERACTING); assert(knp->k3p->transfer.fd != -1); assert(knp->server_info != NULL); assert(self->transfer.fd == -1 || self->cmd_type); assert(self->res_type == 0); assert(self->res_payload == NULL); assert(self->serv_error_msg == NULL); int error = 0; uint32_t msg_type; /* The local payload is used to transfer the data of the messages. It may * eventually become the result payload of the query. */ kbuffer *local_payload = kbuffer_new(1024); /* Set the operation timeout. */ self->transfer.op_timeout = knp->timeout; /* Try. */ do { /* If we're not connected, connect to the server. */ if (self->transfer.fd == -1) { error = knp_query_connect(self, knp); if (error) break; /* Do login. */ if (self->login_type != KNP_CMD_LOGIN_ANON) { /* Write the login message. */ if (self->login_type == KNP_CMD_LOGIN_USER) { knp_msg_write_kstr(local_payload, &knp->server_info->kps_login); knp_msg_write_kstr(local_payload, &knp->server_info->kps_pwd); knp_msg_write_uint32(local_payload, knp->server_info->encrypted_pwd_flag); } else { assert(self->login_type == KNP_CMD_LOGIN_OTUT); assert(self->login_otut != NULL); knp_msg_write_kstr(local_payload, self->login_otut); } /* Send the login message. */ error = knp_query_send_msg(self, self->login_type, local_payload, knp->k3p); if (error) break; /* Receive the reply. */ error = knp_query_recv_msg(self, &msg_type, local_payload, knp->k3p); if (error) break; /* Upgrade required. */ if (msg_type == KNP_RES_UPGRADE_PLUGIN || msg_type == KNP_RES_UPGRADE_KPS) { knp_query_disconnect(self); self->res_type = msg_type; error = 0; break; } /* Login failed. There are two cases here. If we were only doing a login * to the server, the result type is the error returned by the server. * Otherwise, we set the result type to 'KNP_RES_LOGIN_ERROR', to allow * the caller to distinguish between a login failure and the command * failure. The semantics here are pretty messy :-/. */ if (msg_type != KNP_RES_LOGIN_OK) { knp_query_disconnect(self); if (self->cmd_type) self->res_type = KNP_RES_LOGIN_ERROR; else self->res_type = msg_type; error = -1; break; } /* Assign the result message type and payload to the query. */ self->res_type = msg_type; self->res_payload = local_payload; } } /* If there is a command, process it. */ if (self->cmd_type) { assert(self->cmd_payload); /* Clear the result message type and payload, if any. */ self->res_type = 0; self->res_payload = NULL; /* Send the command message. */ error = knp_query_send_msg(self, self->cmd_type, self->cmd_payload, knp->k3p); if (error) break; /* Receive the result. */ error = knp_query_recv_msg(self, &msg_type, local_payload, knp->k3p); if (error) break; /* Assign the result message type and payload to the query. */ self->res_type = msg_type; self->res_payload = local_payload; } } while (0); /* A miscellaneous error occured. */ if (error == -1) { /* We did not handle the error yet. Convert it to a server error. */ if (! self->res_type) { knp_query_handle_conn_error(self, KMO_SERROR_MISC); } /* It's handled. */ error = 0; } /* Destroy the local buffer, if it did not become the result payload. */ if (self->res_payload != local_payload) kbuffer_destroy(local_payload); assert((self->res_type && ! error) || (! self->res_type && (error == -2 || error == -3))); return error; }
/** initialize an otut structure. */ int tagcrypt_otut_init(struct tagcrypt_otut *otut) { otut->addr = kbuffer_new(1); otut->data = kbuffer_new(1); return 0; }
int tagcrypt_ticket_init(struct tagcrypt_ticket * ticket) { ticket->otut_addr = kbuffer_new(256); return 0; }