void kmocrypt_get_kpg_host2(struct kmocrypt_signature2 *self, kstr *addr, int *port) { struct kpg_data *kpg = (struct kpg_data *) self->subpacket_array[KMO_SP_TYPE_KPG]->data; if (kpg->type == 0) { kstr_assign_kstr(addr, &kpg->addr); *port = kpg->port; } }
static void test_kstr() { kstr str1, str2, str3; kstr_init(&str1); kstr_init_cstr(&str2, "bar"); kstr_init_kstr(&str3, &str2); assert(kstr_equal_cstr(&str2, "bar")); assert(kstr_equal_kstr(&str2, &str3)); kstr_assign_cstr(&str3, "foobar"); kstr_assign_kstr(&str1, &str3); kstr_sf(&str2, "%sbar", "foo"); assert(kstr_equal_kstr(&str3, &str2)); assert(kstr_equal_kstr(&str1, &str2)); kstr_sf(&str2, "%s buffer to grow", "I want my"); assert(kstr_equal_cstr(&str2, "I want my buffer to grow")); kstr_clear(&str2); assert(kstr_equal_cstr(&str2, "")); kstr_append_char(&str2, 'f'); kstr_append_char(&str2, 'o'); kstr_assign_cstr(&str1, "ob"); kstr_append_kstr(&str2, &str1); kstr_append_cstr(&str2, "ar"); assert(kstr_equal_cstr(&str2, "foobar")); kstr_free(&str1); kstr_free(&str2); kstr_free(&str3); }
kstr *kdclient_format_error(const char *file, int line, const char *msg, va_list va) { char *p; kstr *err_msg, *err; kstr err_fmt; /* Search for @ */ p = strstr(msg, "@"); if (p) { kstr_init_buf(&err_fmt, msg, p - msg); err_msg = kerror_str_n(0); kstr_append_kstr(&err_fmt, err_msg); kstr_destroy(err_msg); kstr_append_cstr(&err_fmt, p + 1); } else kstr_init_cstr(&err_fmt, msg); err = kmalloc(sizeof(kstr)); kstr_init_sfv(err, err_fmt.data, va); /* Add [file:line] before error message. */ kstr_sf(&err_fmt, "[%s:%d] %s", file, line, err->data); kstr_assign_kstr(err, &err_fmt); kstr_clean(&err_fmt); return err; }
/* This function normalizes a path. It simplifies the directory portion and * makes the path absolute if requested. */ void kpath_normalize(kstr *path, int absolute_flag, int format) { struct kpath_dir dir; kstr dir_path, filename, ext; kstr_init(&dir_path); kstr_init(&filename); kstr_init(&ext); kpath_dir_init(&dir); /* If requested, make the path absolute. */ if (absolute_flag) kpath_make_absolute(path, format); /* Split the path. */ kpath_split(path, &dir_path, &filename, &ext, format); /* Decompose, simplify and recompose the directory portion. */ kpath_decompose_dir(&dir_path, &dir, format); kpath_simplify_dir(&dir); kpath_recompose_dir(&dir_path, &dir, format); /* Recompose the path. */ kstr_assign_kstr(path, &dir_path); kstr_append_kstr(path, &filename); if (ext.slen) { kstr_append_char(path, '.'); kstr_append_kstr(path, &ext); } kpath_dir_clean(&dir); kstr_clean(&dir_path); kstr_clean(&filename); kstr_clean(&ext); }
void anp_msg_write_kstr(struct anp_msg *self, kstr *str) { struct anp_element *el = anp_element_new(); el->type = ANP_STR; el->str = kstr_new(); kstr_assign_kstr(el->str, str); karray_push(&self->element_array, el); anp_write_kstr(&self->payload, el->str); }
void kmo_seterror(const char *format, ...) { /* Make the sprintf(). */ va_list arg; va_start(arg, format); kstr_sfv(&kmo_scratch_str, format, arg); va_end(arg); /* Set the error string. */ kstr_assign_kstr(&kmo_error_str, &kmo_scratch_str); }
/* This function handles a connection error that occurred while processing a * query. Normally the connection error message should have been set by * kmo_seterror(). The KNP connection is closed if it is open. */ static void knp_query_handle_conn_error(struct knp_query *query, int serv_error_id) { kmod_log_msg(3, "knp_query_handle_conn_error() called.\n"); assert(! query->res_type && query->res_payload == NULL); query->res_type = KNP_RES_SERV_ERROR; query->serv_error_id = serv_error_id; query->serv_error_msg = kstr_new(); kstr_assign_kstr(query->serv_error_msg, kmo_kstrerror()); knp_query_disconnect(query); }
/* This function recomposes a directory path from its subcomponents. If the * directory path has no absolute part and no other components, the directory * path will be empty. Otherwise, the directory path will end with a delimiter. */ void kpath_recompose_dir(kstr *path, struct kpath_dir *dir, int format) { int i; kstr_reset(path); if (dir->abs_part.slen) kstr_assign_kstr(path, &dir->abs_part); for (i = 0; i < dir->components.size; i++) { kstr_append_kstr(path, (kstr *) dir->components.data[i]); kstr_append_char(path, kpath_delim(format)); } }
/* This function creates and initializes a KNP query. * The login OTUT must be set manually if it's needed. */ struct knp_query * knp_query_new(int contact, int login_type, int cmd_type, kbuffer *cmd_payload, kstr *all_req_str) { struct knp_query *query = (struct knp_query *) kmo_calloc(sizeof(struct knp_query)); query->contact = contact; kstr_init(&query->server_addr); query->login_type = login_type; query->cmd_type = cmd_type; query->cmd_payload = cmd_payload; kmo_data_transfer_init(&query->transfer); query->transfer.driver = kmo_sock_driver; kstr_assign_kstr(&query->all_req_str, all_req_str); return query; }
/* This function converts a path to an absolute path, if needed. */ void kpath_make_absolute(kstr *path, int format) { kstr tmp; /* Return if the path is already absolute. */ if (kpath_is_absolute(path, format)) return; kstr_init(&tmp); /* Get the current working directory and append the relative path to the * current working directory. */ kpath_getcwd(&tmp); kstr_append_kstr(&tmp, path); kstr_assign_kstr(path, &tmp); kstr_clean(&tmp); }
/* Replace all occurences of the string 'from' with the string 'to' in the * string specified. */ void kstr_replace(kstr *self, char *from, char *to) { kstr tmp; int i = 0; int l = strlen(from); assert(l); kstr_init(&tmp); while (i < self->slen) { if (! strncmp(self->data + i, from, l)) { kstr_append_cstr(&tmp, to); i += l; } else { kstr_append_char(&tmp, self->data[i]); i++; } } kstr_assign_kstr(self, &tmp); kstr_clean(&tmp); }
void kmo_setkerror(kstr *str) { kstr_assign_kstr(&kmo_error_str, str); }
/* This function loops communicating with the proxy. It returns 0 or -1. */ static int kcd_vnc_proxy_comm_loop(struct kcd_vnc_mode_state *vms) { int error = 0; struct kcd_ticket_mode_state *tms = vms->tms; struct kcd_client *client = tms->client; struct kproxy_end client_end, proxy_end; /* select() doesn't like huge values for time. */ int64_t deadline = ktime_set_deadline(MIN(tms->license_info.vnc_session_time * 1000llu, 10*24*60*60*1000llu)); int64_t remaining; kmod_log_msg(KCD_LOG_BRIEF, "kcd_vnc_proxy_comm_loop() called.\n"); kproxy_end_init(&client_end, client->sock, &client->conn, "client", TRANS_BUF_SIZE); kproxy_end_init(&proxy_end, vms->proxy_sock, NULL, "proxy", TRANS_BUF_SIZE); do { /* Receive the initial synchronization byte. */ kmod_log_msg(KCD_LOG_VNC, "kcd_vnc_proxy_comm_loop: receiving sync byte.\n"); while (1) { char byte; int r = ktls_recv(&client->conn, &byte, 1); if (r == 1) break; if (r == -1) { error = -4; break; } kcd_ticket_mode_prepare_wait(tms); kselect_add_read(&tms->sel, client->sock); error = kcd_ticket_mode_wait(tms, -1); if (error) break; } if (error) break; /* Enter the proxy loop. */ kmod_log_msg(KCD_LOG_VNC, "kcd_vnc_proxy_comm_loop: entering proxy loop.\n"); while (1) { /* Transfer data as required. */ kproxy_do_xfer(&client_end, &proxy_end, NULL); kcd_process_do_xfer(&vms->process); /* At least one side of the connection was lost, check if we're done. */ if (kproxy_is_finished(&client_end, &proxy_end)) { error = -4; break; } /* Check deadline, compute remaining. */ if (ktime_check_deadline(deadline, &remaining)) { error = -4; kmod_set_error("maximum screen sharing session time reached"); vms->end_error_code = KANP_RES_FAIL_RESOURCE_QUOTA; kstr_assign_kstr(&vms->end_error_msg, kmod_kstrerror()); break; } /* Block in select. */ kcd_ticket_mode_prepare_wait(tms); kproxy_prepare_select(&tms->sel, &client_end, &proxy_end); kcd_process_prepare_select(&vms->process, &tms->sel); kmod_log_msg(KCD_LOG_VNC, "kproxy_loop: about to wait in select().\n"); error = kcd_ticket_mode_wait(tms, remaining); kmod_log_msg(KCD_LOG_VNC, "kproxy_loop: out of select().\n"); if (error) break; } if (error) break; } while (0); kmod_log_msg(KCD_LOG_BRIEF, "kcd_vnc_proxy_comm_loop(): exiting: %s.\n", kmod_strerror()); kproxy_end_clean(&client_end); kproxy_end_clean(&proxy_end); if (error == -4) { /* Set a generic end error code and message. */ if (!vms->end_error_code) { vms->end_error_code = KANP_RES_FAIL_GEN; kstr_assign_kstr(&vms->end_error_msg, kmod_kstrerror()); } error = 0; } return error; }
/* This function connects to the specified server (possibly through a proxy) and * negociates a SSL session. REMARK: a backport was applied to this function. It * was ugly in the first place, the backport didn't help any. All of it is * rewritten in the next version. REMARK 2: whooops, modified it again. It's * getting prettier by the minute. * This function sets the KMO error string. It returns 0, -1, -2, or -3. */ static int knp_query_connect(struct knp_query *self, struct knp_proto *knp) { assert(self->transfer.fd == -1); assert(self->ssl_driver == NULL); kmod_log_msg(3, "knp_query_connect() called.\n"); int error = 0; kstr str; int use_srv = 0; int use_proxy = 0; kstr proxy_addr; uint32_t proxy_port = 0; kstr proxy_login; kstr proxy_pwd; char *cert = NULL; struct kmo_data_transfer *transfer = &self->transfer; kstr_init(&str); kstr_init(&proxy_addr); kstr_init(&proxy_login); kstr_init(&proxy_pwd); /* Try. */ do { /* We're contacting the KPS. */ if (self->contact == KNP_CONTACT_KPS && k3p_is_using_kps(knp->server_info)) { kstr_assign_kstr(&self->server_addr, &knp->server_info->kps_net_addr); self->server_port = knp->server_info->kps_port_num; if (knp->server_info->kps_use_proxy) { use_proxy = 1; kstr_assign_kstr(&proxy_addr, &knp->server_info->kps_proxy_net_addr); proxy_port = knp->server_info->kps_proxy_port_num; kstr_assign_kstr(&proxy_login, &knp->server_info->kps_proxy_login); kstr_assign_kstr(&proxy_pwd, &knp->server_info->kps_proxy_pwd); } } /* We're contacting the KOS. */ else { #ifdef __DEBUG_KOS_ADDRESS__ kstr_assign_cstr(&self->server_addr, __DEBUG_KOS_ADDRESS__); if (ops_address || ous_address || ots_address || iks_address || eks_address) {} #else /* This is the option to use a one-stop server for all online service requests. */ if (self->all_req_str.slen > 0) { kstr_assign_kstr(&self->server_addr, &self->all_req_str); } else if (knp->server_info->kos_use_proxy || knp->use_kpg) { switch (self->contact) { case KNP_CONTACT_KPS: kstr_assign_cstr(&self->server_addr, ops_address); break; case KNP_CONTACT_OPS: kstr_assign_cstr(&self->server_addr, ops_address); break; case KNP_CONTACT_OUS: kstr_assign_cstr(&self->server_addr, ous_address); break; case KNP_CONTACT_OTS: kstr_assign_cstr(&self->server_addr, ots_address); break; case KNP_CONTACT_IKS: kstr_assign_cstr(&self->server_addr, iks_address); break; case KNP_CONTACT_EKS: kstr_assign_cstr(&self->server_addr, eks_address); break; default: assert(0); }; if (knp->use_kpg) { switch (self->contact) { case KNP_CONTACT_OPS: kstr_assign_cstr(&self->server_addr, knp->kpg_addr.data); break; case KNP_CONTACT_OUS: kstr_assign_cstr(&self->server_addr, knp->kpg_addr.data); break; case KNP_CONTACT_OTS: kstr_assign_cstr(&self->server_addr, knp->kpg_addr.data); break; }; } } else { use_srv = 1; switch (self->contact) { case KNP_CONTACT_KPS: kstr_assign_cstr(&self->server_addr, srv_ops_address); break; case KNP_CONTACT_OPS: kstr_assign_cstr(&self->server_addr, srv_ops_address); break; case KNP_CONTACT_OUS: kstr_assign_cstr(&self->server_addr, srv_ous_address); break; case KNP_CONTACT_OTS: kstr_assign_cstr(&self->server_addr, srv_ots_address); break; case KNP_CONTACT_IKS: kstr_assign_cstr(&self->server_addr, srv_iks_address); break; case KNP_CONTACT_EKS: kstr_assign_cstr(&self->server_addr, srv_eks_address); break; default: assert(0); }; } #endif #ifdef __DEBUG_KOS_PORT__ self->server_port = __DEBUG_KOS_PORT__; if (kos_port) {} #else self->server_port = kos_port; if (knp->use_kpg) { switch (self->contact) { case KNP_CONTACT_OPS: self->server_port = knp->kpg_port; break; case KNP_CONTACT_OUS: self->server_port = knp->kpg_port; break; case KNP_CONTACT_OTS: self->server_port = knp->kpg_port; break; }; } #endif if (knp->server_info->kos_use_proxy) { use_proxy = 1; kstr_assign_kstr(&proxy_addr, &knp->server_info->kos_proxy_net_addr); proxy_port = knp->server_info->kos_proxy_port_num; kstr_assign_kstr(&proxy_login, &knp->server_info->kos_proxy_login); kstr_assign_kstr(&proxy_pwd, &knp->server_info->kos_proxy_pwd); } #ifdef NDEBUG cert = kos_cert; #else if (kos_cert) {} #endif } /* Validate our contact information. */ if (self->server_addr.slen == 0 || self->server_port == 0) { kmo_seterror("invalid server information"); knp_query_handle_conn_error(self, KMO_SERROR_MISC); error = -1; break; } if (use_proxy && (proxy_addr.slen == 0 || proxy_port == 0)) { kmo_seterror("invalid proxy information"); knp_query_handle_conn_error(self, KMO_SERROR_MISC); error = -1; break; } /* Connect to the proxy or the end server directly. */ if (! use_srv) { error = kmo_sock_create(&transfer->fd); if (error) break; error = kmo_sock_set_unblocking(transfer->fd); if (error) break; error = kmo_sock_connect(transfer->fd, use_proxy ? proxy_addr.data : self->server_addr.data, use_proxy ? proxy_port : self->server_port); if (error) { knp_query_handle_conn_error(self, KMO_SERROR_UNREACHABLE); break; } kstr_sf(&str, "cannot connect to %s", use_proxy ? proxy_addr.data : self->server_addr.data); error = knp_query_wait_for_data(self, 0, str.data, knp->k3p); if (error) { if (error == -1) self->serv_error_id = KMO_SERROR_UNREACHABLE; break; } error = kmo_sock_connect_check(transfer->fd, use_proxy ? proxy_addr.data : self->server_addr.data); if (error) { knp_query_handle_conn_error(self, KMO_SERROR_UNREACHABLE); break; } /* If there is a proxy, asks it to connect us to the end server. */ if (use_proxy) { error = knp_handle_proxy(self, knp->k3p, &proxy_login, &proxy_pwd); if (error) break; } } /* Connect using the SRV entries. */ else { error = knp_query_srv_connect(self, knp, self->server_addr.data); if (error) break; } /* Negociate the SSL session. */ error = knp_negociate_ssl_session(self, cert, knp->k3p); if (error) break; } while (0); if (error) knp_query_disconnect(self); kstr_free(&str); kstr_free(&proxy_addr); kstr_free(&proxy_login); kstr_free(&proxy_pwd); return error; }
/* This function decomposes the directory path specified into an array of * subcomponents. If the path is absolute, the absolute part will be something * like 'C:\' on Windows and '/' on UNIX, otherwise it will be empty. The * remaining components will not contain delimiters. * * The path 'C:/toto/bar' will yield ('C:\', 'toto', 'bar') on Windows with alt * support. * The path '/toto/bar/' will yield ('/', 'toto', 'bar') on UNIX. * The path './../foo/' will yield ('.', '..', 'foo'). * The path '' will yield (). */ void kpath_decompose_dir(kstr *path, struct kpath_dir *dir, int format) { int scan_pos = 0; kstr cur_component; /* Get the platform format. */ int platform_format = kpath_get_platform_format(format); /* Determine if the path is absolute. */ int is_absolute = kpath_is_absolute(path, format); kstr_init(&cur_component); kpath_dir_reset(dir); /* If the path is absolute, obtain the absolute part. */ if (is_absolute) { if (platform_format == KPATH_FORMAT_UNIX) { kstr_append_char(&dir->abs_part, '/'); scan_pos = 1; } else { kstr_append_buf(&dir->abs_part, path->data, 2); kstr_append_char(&dir->abs_part, kpath_delim(format)); scan_pos = 3; } } /* Scan the rest of the path. */ while (scan_pos < path->slen) { /* We encountered a delimiter. */ if (kpath_is_delim(path->data[scan_pos], format)) { /* If the current component is empty, ignore it. Otherwise, add the * component in the component array. */ if (cur_component.slen) { kstr *s = kstr_new(); kstr_assign_kstr(s, &cur_component); karray_push(&dir->components, s); } /* Reset the current component. */ kstr_reset(&cur_component); } /* Append the current character. */ else kstr_append_char(&cur_component, path->data[scan_pos]); scan_pos++; } /* Add the last component, if any, in the component array. */ if (cur_component.slen) { kstr *s = kstr_new(); kstr_assign_kstr(s, &cur_component); karray_push(&dir->components, s); } kstr_clean(&cur_component); }
/* This function gets the element at pos in an anp_msg as a string. This * function sets the KMOD error string. It returns -1 on failure. */ int anp_msg_get_kstr(struct anp_msg *self, int pos, kstr *str) { struct anp_element *el = (struct anp_element *) karray_get(&self->element_array, pos); if (anp_msg_get_ensure_type(el, pos, ANP_STR)) return -1; kstr_assign_kstr(str, el->str); return 0; }