diff options
Diffstat (limited to 'sesman')
-rw-r--r-- | sesman/chansrv/Makefile.am | 6 | ||||
-rw-r--r-- | sesman/chansrv/chansrv_common.c | 73 | ||||
-rw-r--r-- | sesman/chansrv/chansrv_common.h | 27 | ||||
-rw-r--r-- | sesman/chansrv/pulse/module-xrdp-source.c | 38 | ||||
-rw-r--r-- | sesman/chansrv/sound.c | 153 | ||||
-rw-r--r-- | sesman/session.c | 10 | ||||
-rw-r--r-- | sesman/verify_user.c | 9 | ||||
-rw-r--r-- | sesman/verify_user_pam.c | 28 |
8 files changed, 272 insertions, 72 deletions
diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 81218db1..7a97c136 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -9,7 +9,8 @@ EXTRA_DIST = \ rail.h \ sound.h \ xcommon.h \ - mlog.h + mlog.h \ + chansrv_common.h EXTRA_DEFINES = EXTRA_INCLUDES = @@ -48,7 +49,8 @@ xrdp_chansrv_SOURCES = \ drdynvc.c \ chansrv_fuse.c \ irp.c \ - fifo.c + fifo.c \ + chansrv_common.c xrdp_chansrv_LDFLAGS = \ $(EXTRA_FLAGS) diff --git a/sesman/chansrv/chansrv_common.c b/sesman/chansrv/chansrv_common.c new file mode 100644 index 00000000..fd26da7c --- /dev/null +++ b/sesman/chansrv/chansrv_common.c @@ -0,0 +1,73 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2009-2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "chansrv_common.h" + +/** + * Assemble fragmented incoming packets into one stream + * + * @param src stream that contains partial data + * @param dest stream that contains entire data + * @param chan_flags fragmentation flags + * @param length bytes in this packet + * @param total_length total length of assembled packet + * + * @return 1 when all data has been assembled, 0 otherwise + * + * NOTE: it is the responsibility of the caller to free dest stream + ****************************************************************************/ +int +read_entire_packet(struct stream *src, struct stream **dest, int chan_flags, + int length, int total_length) +{ + struct stream *ls; + + if ((chan_flags & 3) == 3) + { + /* packet not fragmented */ + xstream_new(ls, total_length); + xstream_copyin(ls, src->p, length); + ls->p = ls->data; + *dest = ls; + return 1; + } + + /* is this the first fragmented packet? */ + if (chan_flags & 1) + { + xstream_new(ls, total_length); + *dest = ls; + } + else + { + ls = *dest; + } + + xstream_copyin(ls, src->p, length); + + /* in last packet, chan_flags & 0x02 will be true */ + if (chan_flags & 0x02) + { + /* rewind stream */ + ls->p = ls->data; + return 1; + } + + return 0; +} + diff --git a/sesman/chansrv/chansrv_common.h b/sesman/chansrv/chansrv_common.h new file mode 100644 index 00000000..833e3359 --- /dev/null +++ b/sesman/chansrv/chansrv_common.h @@ -0,0 +1,27 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2009-2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CHANSRV_COMMON_H +#define _CHANSRV_COMMON_H + +#include "parse.h" + +int read_entire_packet(struct stream *src, struct stream **dest, int chan_flags, int length, int total_length); + +#endif + diff --git a/sesman/chansrv/pulse/module-xrdp-source.c b/sesman/chansrv/pulse/module-xrdp-source.c index 1c03b069..3d73fd03 100644 --- a/sesman/chansrv/pulse/module-xrdp-source.c +++ b/sesman/chansrv/pulse/module-xrdp-source.c @@ -71,7 +71,7 @@ PA_MODULE_USAGE( #define DEFAULT_SOURCE_NAME "xrdp-source" #define DEFAULT_LATENCY_TIME 10 -#define MAX_LATENCY_USEC (PA_USEC_PER_SEC * 2) +#define MAX_LATENCY_USEC 1000 #define CHANSRV_PORT_STR "/tmp/.xrdp/xrdp_chansrv_audio_in_socket_%d" struct userdata { @@ -144,6 +144,32 @@ static void source_update_requested_latency_cb(pa_source *s) { u->block_usec = pa_source_get_requested_latency_within_thread(s); } +static int lsend(int fd, char *data, int bytes) { + int sent = 0; + int error; + while (sent < bytes) { + error = send(fd, data + sent, bytes - sent, 0); + if (error < 1) { + return error; + } + sent += error; + } + return sent; +} + +static int lrecv(int fd, char *data, int bytes) { + int recved = 0; + int error; + while (recved < bytes) { + error = recv(fd, data + recved, bytes - recved, 0); + if (error < 1) { + return error; + } + recved += error; + } + return recved; +} + static int data_get(struct userdata *u, pa_memchunk *chunk) { int fd; @@ -190,7 +216,7 @@ static int data_get(struct userdata *u, pa_memchunk *chunk) { buf[9] = 0; buf[10] = 0; - send(u->fd, buf, 11, 0); + lsend(u->fd, buf, 11); u->want_src_data = 1; pa_log_debug("###### started recording"); } @@ -208,10 +234,10 @@ static int data_get(struct userdata *u, pa_memchunk *chunk) { buf[9] = (unsigned char) chunk->length; buf[10] = (unsigned char) ((chunk->length >> 8) & 0xff); - send(u->fd, buf, 11, 0); + lsend(u->fd, buf, 11); /* read length of data available */ - recv(u->fd, ubuf, 2, 0); + lrecv(u->fd, (char *) ubuf, 2); bytes = ((ubuf[1] << 8) & 0xff00) | (ubuf[0] & 0xff); if (bytes == 0) { @@ -220,7 +246,7 @@ static int data_get(struct userdata *u, pa_memchunk *chunk) { } /* get data */ - bytes = recv(u->fd, data, bytes, 0); + bytes = lrecv(u->fd, data, bytes); pa_memblock_release(chunk->memblock); @@ -272,7 +298,7 @@ static void thread_func(void *userdata) { buf[9] = 0; buf[10] = 0; - send(u->fd, buf, 11, 0); + lsend(u->fd, buf, 11); u->want_src_data = 0; pa_log_debug("###### stopped recording"); } diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c index f5e17fef..9943a15b 100644 --- a/sesman/chansrv/sound.c +++ b/sesman/chansrv/sound.c @@ -43,9 +43,11 @@ static struct trans *g_audio_c_trans_in = 0; /* connection */ static int g_training_sent_time = 0; static int g_cBlockNo = 0; static int g_bytes_in_stream = 0; -static FIFO in_fifo; +static FIFO g_in_fifo; +static int g_bytes_in_fifo = 0; static struct stream *g_stream_inp = NULL; +static struct stream *g_stream_incoming_packet = NULL; #define BBUF_SIZE (1024 * 8) char g_buffer[BBUF_SIZE]; @@ -145,23 +147,18 @@ static int g_client_input_format_index = 0; static int g_server_input_format_index = 0; /* microphone related */ -static int APP_CC -sound_send_server_input_formats(void); -static int APP_CC -sound_process_input_format(int aindex, int wFormatTag, +static int APP_CC sound_send_server_input_formats(void); +static int APP_CC sound_process_input_format(int aindex, int wFormatTag, int nChannels, int nSamplesPerSec, int nAvgBytesPerSec, int nBlockAlign, int wBitsPerSample, int cbSize, char *data); -static int APP_CC -sound_process_input_formats(struct stream *s, int size); -static int APP_CC -sound_input_start_recording(void); -static int APP_CC -sound_input_stop_recording(void); -static int APP_CC -sound_process_input_data(struct stream *s, int bytes); -static int DEFAULT_CC -sound_sndsrvr_source_data_in(struct trans *trans); +static int APP_CC sound_process_input_formats(struct stream *s, int size); +static int APP_CC sound_input_start_recording(void); +static int APP_CC sound_input_stop_recording(void); +static int APP_CC sound_process_input_data(struct stream *s, int bytes); +static int DEFAULT_CC sound_sndsrvr_source_data_in(struct trans *trans); +static int APP_CC sound_start_source_listener(); +static int APP_CC sound_start_sink_listener(); /*****************************************************************************/ static int APP_CC @@ -681,36 +678,21 @@ sound_sndsrvr_source_conn_in(struct trans *trans, struct trans *new_trans) int APP_CC sound_init(void) { - char port[256]; - LOG(0, ("sound_init:")); g_memset(g_sent_flag, 0, sizeof(g_sent_flag)); + g_stream_incoming_packet = NULL; /* init sound output */ sound_send_server_output_formats(); - - g_audio_l_trans_out = trans_create(TRANS_MODE_UNIX, 128 * 1024, 8192); - g_audio_l_trans_out->is_term = g_is_term; - g_snprintf(port, 255, CHANSRV_PORT_OUT_STR, g_display_num); - g_audio_l_trans_out->trans_conn_in = sound_sndsrvr_sink_conn_in; - - if (trans_listen(g_audio_l_trans_out, port) != 0) - LOG(0, ("sound_init: trans_listen failed")); + sound_start_sink_listener(); /* init sound input */ sound_send_server_input_formats(); - - g_audio_l_trans_in = trans_create(TRANS_MODE_UNIX, 128 * 1024, 8192); - g_audio_l_trans_in->is_term = g_is_term; - g_snprintf(port, 255, CHANSRV_PORT_IN_STR, g_display_num); - g_audio_l_trans_in->trans_conn_in = sound_sndsrvr_source_conn_in; - - if (trans_listen(g_audio_l_trans_in, port) != 0) - LOG(0, ("sound_init: trans_listen failed")); + sound_start_source_listener(); /* save data from sound_server_source */ - fifo_init(&in_fifo, 100); + fifo_init(&g_in_fifo, 100); return 0; } @@ -744,7 +726,7 @@ sound_deinit(void) g_audio_c_trans_in = 0; } - fifo_deinit(&in_fifo); + fifo_deinit(&g_in_fifo); return 0; } @@ -759,31 +741,39 @@ sound_data_in(struct stream *s, int chan_id, int chan_flags, int length, { int code; int size; + int ok_to_free = 1; - in_uint8(s, code); - in_uint8s(s, 1); - in_uint16_le(s, size); + if (!read_entire_packet(s, &g_stream_incoming_packet, chan_flags, + length, total_length)) + { + return 0; + } + + in_uint8(g_stream_incoming_packet, code); + in_uint8s(g_stream_incoming_packet, 1); + in_uint16_le(g_stream_incoming_packet, size); switch (code) { case SNDC_WAVECONFIRM: - sound_process_wave_confirm(s, size); + sound_process_wave_confirm(g_stream_incoming_packet, size); break; case SNDC_TRAINING: - sound_process_training(s, size); + sound_process_training(g_stream_incoming_packet, size); break; case SNDC_FORMATS: - sound_process_output_formats(s, size); + sound_process_output_formats(g_stream_incoming_packet, size); break; case SNDC_REC_NEGOTIATE: - sound_process_input_formats(s, size); + sound_process_input_formats(g_stream_incoming_packet, size); break; case SNDC_REC_DATA: - sound_process_input_data(s, size); + sound_process_input_data(g_stream_incoming_packet, size); + ok_to_free = 0; break; default: @@ -791,6 +781,12 @@ sound_data_in(struct stream *s, int chan_id, int chan_flags, int length, break; } + if (ok_to_free && g_stream_incoming_packet) + { + xstream_free(g_stream_incoming_packet); + g_stream_incoming_packet = NULL; + } + return 0; } @@ -834,7 +830,6 @@ sound_get_wait_objs(tbus *objs, int *count, int *timeout) int APP_CC sound_check_wait_objs(void) { - if (g_audio_l_trans_out != 0) { if (trans_check_wait_objs(g_audio_l_trans_out) != 0) @@ -852,6 +847,7 @@ sound_check_wait_objs(void) LOG(10, ("sound_check_wait_objs: g_audio_c_trans_out returned non-zero")); trans_delete(g_audio_c_trans_out); g_audio_c_trans_out = 0; + sound_start_sink_listener(); } } @@ -872,6 +868,7 @@ sound_check_wait_objs(void) LOG(10, ("sound_check_wait_objs: g_audio_c_trans_in returned non-zero")); trans_delete(g_audio_c_trans_in); g_audio_c_trans_in = 0; + sound_start_source_listener(); } } @@ -1045,9 +1042,12 @@ sound_input_start_recording(void) { struct stream* s; + LOG(10, ("sound_input_start_recording:")); + /* if there is any data in FIFO, discard it */ - while ((s = (struct stream *) fifo_remove(&in_fifo)) != NULL) + while ((s = (struct stream *) fifo_remove(&g_in_fifo)) != NULL) xstream_free(s); + g_bytes_in_fifo = 0; xstream_new(s, 1024); @@ -1079,6 +1079,8 @@ sound_input_stop_recording(void) { struct stream* s; + LOG(10, ("sound_input_stop_recording:")); + xstream_new(s, 1024); /* @@ -1102,19 +1104,25 @@ sound_input_stop_recording(void) * Process data: xrdp <- client *****************************************************************************/ -static unsigned char data = 0; - static int APP_CC sound_process_input_data(struct stream *s, int bytes) { struct stream *ls; + LOG(0, ("sound_process_input_data: bytes %d g_bytes_in_fifo %d", + bytes, g_bytes_in_fifo)); + + /* cap data in fifo */ + if (g_bytes_in_fifo > 8 * 1024) + { + return 0; + } xstream_new(ls, bytes); - memcpy(ls->data, s->p, bytes); + g_memcpy(ls->data, s->p, bytes); ls->p += bytes; s_mark_end(ls); - - fifo_insert(&in_fifo, (void *) ls); + fifo_insert(&g_in_fifo, (void *) ls); + g_bytes_in_fifo += bytes; return 0; } @@ -1147,6 +1155,7 @@ sound_sndsrvr_source_data_in(struct trans *trans) ts->p = ts->data + 8; in_uint8(ts, cmd); in_uint16_le(ts, bytes_req); + LOG(10, ("sound_sndsrvr_source_data_in: bytes_req %d", bytes_req)); xstream_new(s, bytes_req + 2); @@ -1158,7 +1167,14 @@ sound_sndsrvr_source_data_in(struct trans *trans) while (bytes_read < bytes_req) { if (g_stream_inp == NULL) - g_stream_inp = (struct stream *) fifo_remove(&in_fifo); + { + g_stream_inp = (struct stream *) fifo_remove(&g_in_fifo); + if (g_stream_inp != NULL) + { + g_bytes_in_fifo -= g_stream_inp->size; + LOG(10, (" g_bytes_in_fifo %d", g_bytes_in_fifo)); + } + } if (g_stream_inp == NULL) { @@ -1212,3 +1228,38 @@ sound_sndsrvr_source_data_in(struct trans *trans) return 0; } + +/** + * Start a listener for microphone redirection connections + *****************************************************************************/ +static int APP_CC +sound_start_source_listener() +{ + char port[1024]; + + g_audio_l_trans_in = trans_create(TRANS_MODE_UNIX, 128 * 1024, 8192); + g_audio_l_trans_in->is_term = g_is_term; + g_snprintf(port, 255, CHANSRV_PORT_IN_STR, g_display_num); + g_audio_l_trans_in->trans_conn_in = sound_sndsrvr_source_conn_in; + if (trans_listen(g_audio_l_trans_in, port) != 0) + LOG(0, ("trans_listen failed")); + return 0; +} + +/** + * Start a listener for speaker redirection connections + *****************************************************************************/ +static int APP_CC +sound_start_sink_listener() +{ + char port[1024]; + + g_audio_l_trans_out = trans_create(TRANS_MODE_UNIX, 128 * 1024, 8192); + g_audio_l_trans_out->is_term = g_is_term; + g_snprintf(port, 255, CHANSRV_PORT_OUT_STR, g_display_num); + g_audio_l_trans_out->trans_conn_in = sound_sndsrvr_sink_conn_in; + if (trans_listen(g_audio_l_trans_out, port) != 0) + LOG(0, ("trans_listen failed")); + return 0; +} + diff --git a/sesman/session.c b/sesman/session.c index 856c969e..4ea48d35 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -460,6 +460,7 @@ session_start_fork(int width, int height, int bpp, char *username, char screen[32]; char text[256]; char passwd_file[256]; + char *pfile; char **pp1 = (char **)NULL; struct session_chain *temp = (struct session_chain *)NULL; struct list *xserver_params = (struct list *)NULL; @@ -633,10 +634,14 @@ session_start_fork(int width, int height, int bpp, char *username, } else if (xpid == 0) /* child */ { - env_set_user(username, passwd_file, display, + pfile = 0; + if (type == SESMAN_SESSION_TYPE_XVNC) + { + pfile = passwd_file; + } + env_set_user(username, pfile, display, g_cfg->session_variables1, g_cfg->session_variables2); - env_check_password_file(passwd_file, password); g_snprintf(text, 255, "%d", g_cfg->sess.max_idle_time); g_setenv("XRDP_SESMAN_MAX_IDLE_TIME", text, 1); @@ -676,6 +681,7 @@ session_start_fork(int width, int height, int bpp, char *username, } else if (type == SESMAN_SESSION_TYPE_XVNC) { + env_check_password_file(passwd_file, password); xserver_params = list_create(); xserver_params->auto_free = 1; diff --git a/sesman/verify_user.c b/sesman/verify_user.c index 98d3dd32..49c475c6 100644 --- a/sesman/verify_user.c +++ b/sesman/verify_user.c @@ -51,6 +51,7 @@ long DEFAULT_CC auth_userpass(char *user, char *pass, int *errorcode) { const char *encr; + const char *epass; struct passwd *spw; struct spwd *stp; @@ -84,8 +85,12 @@ auth_userpass(char *user, char *pass, int *errorcode) /* old system with only passwd */ encr = spw->pw_passwd; } - - return (strcmp(encr, crypt(pass, encr)) == 0); + epass = crypt(pass, encr); + if (epass == 0) + { + return 0; + } + return (strcmp(encr, epass) == 0); } /******************************************************************************/ diff --git a/sesman/verify_user_pam.c b/sesman/verify_user_pam.c index eec12c66..a2b3f93a 100644 --- a/sesman/verify_user_pam.c +++ b/sesman/verify_user_pam.c @@ -118,22 +118,31 @@ auth_userpass(char *user, char *pass, int *errorcode) if (error != PAM_SUCCESS) { - if(errorcode!=NULL){ - *errorcode = error ; - } + if (errorcode != NULL) + { + *errorcode = error; + } g_printf("pam_start failed: %s\r\n", pam_strerror(auth_info->ph, error)); pam_end(auth_info->ph, error); g_free(auth_info); return 0; } + error = pam_set_item(auth_info->ph, PAM_TTY, service_name); + if (error != PAM_SUCCESS) + { + g_printf("pam_set_item failed: %s\r\n", + pam_strerror(auth_info->ph, error)); + } + error = pam_authenticate(auth_info->ph, 0); if (error != PAM_SUCCESS) { - if(errorcode!=NULL){ - *errorcode = error ; - } + if (errorcode != NULL) + { + *errorcode = error; + } g_printf("pam_authenticate failed: %s\r\n", pam_strerror(auth_info->ph, error)); pam_end(auth_info->ph, error); @@ -150,9 +159,10 @@ auth_userpass(char *user, char *pass, int *errorcode) if (error != PAM_SUCCESS) { - if(errorcode!=NULL){ - *errorcode = error ; - } + if (errorcode != NULL) + { + *errorcode = error; + } g_printf("pam_acct_mgmt failed: %s\r\n", pam_strerror(auth_info->ph, error)); pam_end(auth_info->ph, error); |