/* called with the main thread */ static int APP_CC session_start_fork(int width, int height, int bpp, char *username, char *password, tbus data, tui8 type, char *domain, char *program, char *directory, char *client_ip) { int display = 0; int pid = 0; int wmpid = 0; int xpid = 0; int i = 0; char geometry[32]; char depth[32]; char screen[32]; char text[256]; char passwd_file[256]; char **pp1 = (char **)NULL; struct session_chain *temp = (struct session_chain *)NULL; struct list *xserver_params = (struct list *)NULL; time_t ltime; struct tm stime; char execvpparams[2048]; /* initialize (zero out) local variables: */ g_memset(<ime, 0, sizeof(time_t)); g_memset(&stime, 0, sizeof(struct tm)); g_memset(geometry, 0, sizeof(char) * 32); g_memset(depth, 0, sizeof(char) * 32); g_memset(screen, 0, sizeof(char) * 32); g_memset(text, 0, sizeof(char) * 256); g_memset(passwd_file, 0, sizeof(char) * 256); /* check to limit concurrent sessions */ if (g_session_count >= g_cfg->sess.max_sessions) { log_message(LOG_LEVEL_INFO, "max concurrent session limit " "exceeded. login for user %s denied", username); return 0; } temp = (struct session_chain *)g_malloc(sizeof(struct session_chain), 0); if (temp == 0) { log_message(LOG_LEVEL_ERROR, "cannot create new chain " "element - user %s", username); return 0; } temp->item = (struct session_item *)g_malloc(sizeof(struct session_item), 0); if (temp->item == 0) { g_free(temp); log_message(LOG_LEVEL_ERROR, "cannot create new session " "item - user %s", username); return 0; } display = session_get_aval_display_from_chain(); if (display == 0) { g_free(temp->item); g_free(temp); return 0; } pid = g_fork(); if (pid == -1) { } else if (pid == 0) /* child sesman */ { g_tcp_close(g_sck); g_tcp_close(g_thread_sck); auth_start_session(data, display); g_sprintf(geometry, "%dx%d", width, height); g_sprintf(depth, "%d", bpp); g_sprintf(screen, ":%d", display); wmpid = g_fork(); if (wmpid == -1) { } else if (wmpid == 0) /* child (child sesman) xserver */ { wait_for_xserver(display); env_set_user(username, 0, display); if (x_server_running(display)) { auth_set_env(data); if (directory != 0) { if (directory[0] != 0) { g_set_current_dir(directory); } } if (program != 0) { if (program[0] != 0) { g_execlp3(program, program, 0); log_message(LOG_LEVEL_ALWAYS, "error starting program %s for user %s - pid %d", program, username, g_getpid()); } } /* try to execute user window manager if enabled */ if (g_cfg->enable_user_wm) { g_sprintf(text, "%s/%s", g_getenv("HOME"), g_cfg->user_wm); if (g_file_exist(text)) { g_execlp3(text, g_cfg->user_wm, 0); log_message(LOG_LEVEL_ALWAYS, "error starting user " "wm for user %s - pid %d", username, g_getpid()); /* logging parameters */ log_message(LOG_LEVEL_DEBUG, "errno: %d, " "description: %s", errno, g_get_strerror()); log_message(LOG_LEVEL_DEBUG, "execlp3 parameter " "list:"); log_message(LOG_LEVEL_DEBUG, " argv[0] = %s", text); log_message(LOG_LEVEL_DEBUG, " argv[1] = %s", g_cfg->user_wm); } } /* if we're here something happened to g_execlp3 so we try running the default window manager */ g_sprintf(text, "%s/%s", XRDP_CFG_PATH, g_cfg->default_wm); g_execlp3(text, g_cfg->default_wm, 0); log_message( LOG_LEVEL_ALWAYS, "error starting default " "wm for user %s - pid %d", username, g_getpid()); /* logging parameters */ log_message( LOG_LEVEL_DEBUG, "errno: %d, description: " "%s", errno, g_get_strerror()); log_message(LOG_LEVEL_DEBUG, "execlp3 parameter list:"); log_message(LOG_LEVEL_DEBUG, " argv[0] = %s", text); log_message(LOG_LEVEL_DEBUG, " argv[1] = %s", g_cfg->default_wm); /* still a problem starting window manager just start xterm */ g_execlp3("xterm", "xterm", 0); /* should not get here */ log_message(LOG_LEVEL_ALWAYS, "error starting xterm " "for user %s - pid %d", username, g_getpid()); /* logging parameters */ log_message(LOG_LEVEL_DEBUG, "errno: %d, description: " "%s", errno, g_get_strerror()); } else { log_message(LOG_LEVEL_ERROR, "another Xserver might " "already be active on display %d - see log", display); } log_message(LOG_LEVEL_DEBUG, "aborting connection..."); g_exit(0); } else /* parent (child sesman) */ { xpid = g_fork(); if (xpid == -1) { } else if (xpid == 0) /* child */ { env_set_user(username, passwd_file, display); env_check_password_file(passwd_file, password); if (type == SESMAN_SESSION_TYPE_XVNC) { xserver_params = list_create(); xserver_params->auto_free = 1; /* these are the must have parameters */ list_add_item(xserver_params, (long)g_strdup("Xvnc")); list_add_item(xserver_params, (long)g_strdup(screen)); list_add_item(xserver_params, (long)g_strdup("-geometry")); list_add_item(xserver_params, (long)g_strdup(geometry)); list_add_item(xserver_params, (long)g_strdup("-depth")); list_add_item(xserver_params, (long)g_strdup(depth)); list_add_item(xserver_params, (long)g_strdup("-rfbauth")); list_add_item(xserver_params, (long)g_strdup(passwd_file)); /* additional parameters from sesman.ini file */ //config_read_xserver_params(SESMAN_SESSION_TYPE_XVNC, // xserver_params); list_append_list_strdup(g_cfg->vnc_params, xserver_params, 0); /* make sure it ends with a zero */ list_add_item(xserver_params, 0); pp1 = (char **)xserver_params->items; log_message(LOG_LEVEL_INFO, "Xvnc start:%s", dumpItemsToString(xserver_params, execvpparams, 2048)); g_execvp("Xvnc", pp1); } else if (type == SESMAN_SESSION_TYPE_XRDP) { xserver_params = list_create(); xserver_params->auto_free = 1; /* these are the must have parameters */ list_add_item(xserver_params, (long)g_strdup("X11rdp")); list_add_item(xserver_params, (long)g_strdup(screen)); list_add_item(xserver_params, (long)g_strdup("-geometry")); list_add_item(xserver_params, (long)g_strdup(geometry)); list_add_item(xserver_params, (long)g_strdup("-depth")); list_add_item(xserver_params, (long)g_strdup(depth)); /* additional parameters from sesman.ini file */ //config_read_xserver_params(SESMAN_SESSION_TYPE_XRDP, // xserver_params); list_append_list_strdup(g_cfg->rdp_params, xserver_params, 0); /* make sure it ends with a zero */ list_add_item(xserver_params, 0); pp1 = (char **)xserver_params->items; log_message(LOG_LEVEL_INFO, "X11rdp start:%s", dumpItemsToString(xserver_params, execvpparams, 2048)); g_execvp("X11rdp", pp1); } else { log_message(LOG_LEVEL_ALWAYS, "bad session type - " "user %s - pid %d", username, g_getpid()); g_exit(1); } /* should not get here */ log_message(LOG_LEVEL_ALWAYS, "error starting X server " "- user %s - pid %d", username, g_getpid()); /* logging parameters */ log_message(LOG_LEVEL_DEBUG, "errno: %d, description: " "%s", errno, g_get_strerror()); log_message(LOG_LEVEL_DEBUG, "execve parameter list size: " "%d", (xserver_params)->count); for (i = 0; i < (xserver_params->count); i++) { log_message(LOG_LEVEL_DEBUG, " argv[%d] = %s", i, (char *)list_get_item(xserver_params, i)); } list_delete(xserver_params); g_exit(1); } else /* parent (child sesman)*/ { wait_for_xserver(display); g_snprintf(text, 255, "%d", display); g_setenv("XRDP_SESSVC_DISPLAY", text, 1); g_snprintf(text, 255, ":%d.0", display); g_setenv("DISPLAY", text, 1); /* new style waiting for clients */ session_start_sessvc(xpid, wmpid, data, username, display); } } } else /* parent sesman process */ { temp->item->pid = pid; temp->item->display = display; temp->item->width = width; temp->item->height = height; temp->item->bpp = bpp; temp->item->data = data; g_strncpy(temp->item->client_ip, client_ip, 255); /* store client ip data */ g_strncpy(temp->item->name, username, 255); ltime = g_time1(); localtime_r(<ime, &stime); temp->item->connect_time.year = (tui16)(stime.tm_year + 1900); temp->item->connect_time.month = (tui8)stime.tm_mon; temp->item->connect_time.day = (tui8)stime.tm_mday; temp->item->connect_time.hour = (tui8)stime.tm_hour; temp->item->connect_time.minute = (tui8)stime.tm_min; zero_time(&(temp->item->disconnect_time)); zero_time(&(temp->item->idle_time)); temp->item->type = type; temp->item->status = SESMAN_SESSION_STATUS_ACTIVE; temp->next = g_sessions; g_sessions = temp; g_session_count++; } return display; }
/* its the responsibility of the caller to free passwd_file */ int env_set_user(const char *username, char **passwd_file, int display, const struct list *env_names, const struct list *env_values) { int error; int pw_uid; int pw_gid; int uid; int index; int len; char *name; char *value; char *pw_shell; char *pw_dir; char text[256]; char hostname[256]; pw_shell = 0; pw_dir = 0; error = g_getuser_info(username, &pw_gid, &pw_uid, &pw_shell, &pw_dir, 0); if (error == 0) { g_rm_temp_dir(); error = g_setgid(pw_gid); if (error == 0) { error = g_initgroups(username, pw_gid); } if (error == 0) { uid = pw_uid; error = g_setuid(uid); } g_mk_socket_path(0); if (error == 0) { g_clearenv(); g_setenv("SHELL", pw_shell, 1); g_setenv("PATH", "/sbin:/bin:/usr/bin:/usr/local/bin", 1); g_setenv("USER", username, 1); g_setenv("LOGNAME", username, 1); g_sprintf(text, "%d", uid); g_setenv("UID", text, 1); g_setenv("HOME", pw_dir, 1); g_set_current_dir(pw_dir); g_sprintf(text, ":%d.0", display); g_setenv("DISPLAY", text, 1); g_setenv("XRDP_SESSION", "1", 1); /* XRDP_SOCKET_PATH should be set even here, chansrv uses this */ g_setenv("XRDP_SOCKET_PATH", XRDP_SOCKET_PATH, 1); /* pulse sink socket */ g_snprintf(text, sizeof(text) - 1, CHANSRV_PORT_OUT_BASE_STR, display); g_setenv("XRDP_PULSE_SINK_SOCKET", text, 1); /* pulse source socket */ g_snprintf(text, sizeof(text) - 1, CHANSRV_PORT_IN_BASE_STR, display); g_setenv("XRDP_PULSE_SOURCE_SOCKET", text, 1); if ((env_names != 0) && (env_values != 0) && (env_names->count == env_values->count)) { for (index = 0; index < env_names->count; index++) { name = (char *) list_get_item(env_names, index), value = (char *) list_get_item(env_values, index), g_setenv(name, value, 1); } } g_gethostname(hostname, 255); hostname[255] = 0; if (passwd_file != 0) { if (0 == g_cfg->auth_file_path) { /* if no auth_file_path is set, then we go for $HOME/.vnc/sesman_passwd-USERNAME@HOSTNAME:DISPLAY */ if (!g_directory_exist(".vnc")) { if (g_mkdir(".vnc") < 0) { log_message(LOG_LEVEL_ERROR, "Error creating .vnc directory: %s", g_get_strerror()); } } len = g_snprintf(NULL, 0, "%s/.vnc/sesman_passwd-%s@%s:%d", pw_dir, username, hostname, display); *passwd_file = (char *) g_malloc(len + 1, 1); if (*passwd_file != NULL) { /* Try legacy names first, remove if found */ g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd:%d", pw_dir, username, display); if (g_file_exist(*passwd_file)) { log_message(LOG_LEVEL_WARNING, "Removing old " "password file %s", *passwd_file); g_file_delete(*passwd_file); } g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd", pw_dir, username); if (g_file_exist(*passwd_file)) { log_message(LOG_LEVEL_WARNING, "Removing insecure " "password file %s", *passwd_file); g_file_delete(*passwd_file); } g_sprintf(*passwd_file, "%s/.vnc/sesman_passwd-%s@%s:%d", pw_dir, username, hostname, display); } } else { /* we use auth_file_path as requested */ len = g_snprintf(NULL, 0, g_cfg->auth_file_path, username); *passwd_file = (char *) g_malloc(len + 1, 1); if (*passwd_file != NULL) { g_sprintf(*passwd_file, g_cfg->auth_file_path, username); } } if (*passwd_file != NULL) { LOG_DBG("pass file: %s", *passwd_file); } } g_free(pw_dir); g_free(pw_shell); } } else { log_message(LOG_LEVEL_ERROR, "error getting user info for user %s", username); } return error; }
/* its the responsibility of the caller to free passwd_file */ int DEFAULT_CC env_set_user(const char *username, char **passwd_file, int display, const struct list *env_names, const struct list *env_values) { int error; int pw_uid; int pw_gid; int uid; int index; int len; char *name; char *value; char *pw_shell; char *pw_dir; char text[256]; pw_shell = 0; pw_dir = 0; error = g_getuser_info(username, &pw_gid, &pw_uid, &pw_shell, &pw_dir, 0); if (error == 0) { g_rm_temp_dir(); error = g_setgid(pw_gid); if (error == 0) { error = g_initgroups(username, pw_gid); } if (error == 0) { uid = pw_uid; error = g_setuid(uid); } g_mk_temp_dir(0); if (error == 0) { g_clearenv(); g_setenv("SHELL", pw_shell, 1); g_setenv("PATH", "/sbin:/bin:/usr/bin:/usr/local/bin", 1); g_setenv("USER", username, 1); g_sprintf(text, "%d", uid); g_setenv("UID", text, 1); g_setenv("HOME", pw_dir, 1); g_set_current_dir(pw_dir); g_sprintf(text, ":%d.0", display); g_setenv("DISPLAY", text, 1); g_setenv("XRDP_SESSION", "1", 1); if ((env_names != 0) && (env_values != 0) && (env_names->count == env_values->count)) { for (index = 0; index < env_names->count; index++) { name = (char *) list_get_item(env_names, index), value = (char *) list_get_item(env_values, index), g_setenv(name, value, 1); } } if (passwd_file != 0) { if (0 == g_cfg->auth_file_path) { /* if no auth_file_path is set, then we go for $HOME/.vnc/sesman_username_passwd:DISPLAY */ if (!g_directory_exist(".vnc")) { if (g_mkdir(".vnc") < 0) { log_message(LOG_LEVEL_ERROR, "Error creating .vnc directory: %s", g_get_strerror()); } } len = g_snprintf(NULL, 0, "%s/.vnc/sesman_%s_passwd:%d", pw_dir, username, display); *passwd_file = (char *) g_malloc(len + 1, 1); if (*passwd_file != NULL) { /* Try legacy name first, remove if found */ g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd", pw_dir, username); if (g_file_exist(*passwd_file)) { log_message(LOG_LEVEL_WARNING, "Removing insecure " "password file %s", *passwd_file); g_file_delete(*passwd_file); } g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd:%d", pw_dir, username, display); } } else { /* we use auth_file_path as requested */ len = g_snprintf(NULL, 0, g_cfg->auth_file_path, username); *passwd_file = (char *) g_malloc(len + 1, 1); if (*passwd_file != NULL) { g_sprintf(*passwd_file, g_cfg->auth_file_path, username); } } if (*passwd_file != NULL) { LOG_DBG("pass file: %s", *passwd_file); } } g_free(pw_dir); g_free(pw_shell); } } else { log_message(LOG_LEVEL_ERROR, "error getting user info for user %s", username); } return error; }
VOID WINAPI MyServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) { WSADATA w; char text[256]; int pid; //HANDLE event_han; // int fd; // char text[256]; // fd = g_file_open("c:\\temp\\xrdp\\log.txt"); // g_file_write(fd, "hi\r\n", 4); //event_han = RegisterEventSource(0, "xrdp"); //log_event(event_han, "hi xrdp log"); g_threadid = tc_get_threadid(); g_set_current_dir("c:\\temp\\xrdp"); g_listen = 0; WSAStartup(2, &w); g_sync_mutex = tc_mutex_create(); g_sync1_mutex = tc_mutex_create(); pid = g_getpid(); g_snprintf(text, 255, "xrdp_%8.8x_main_term", pid); g_term_event = g_create_wait_obj(text); g_snprintf(text, 255, "xrdp_%8.8x_main_sync", pid); g_sync_event = g_create_wait_obj(text); g_memset(&g_service_status, 0, sizeof(SERVICE_STATUS)); g_service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; g_service_status.dwCurrentState = SERVICE_RUNNING; g_service_status.dwControlsAccepted = SERVICE_CONTROL_INTERROGATE | SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; g_service_status.dwWin32ExitCode = NO_ERROR; g_service_status.dwServiceSpecificExitCode = 0; g_service_status.dwCheckPoint = 0; g_service_status.dwWaitHint = 0; // g_sprintf(text, "calling RegisterServiceCtrlHandler\r\n"); // g_file_write(fd, text, g_strlen(text)); g_ssh = RegisterServiceCtrlHandler("xrdp", MyHandler); if (g_ssh != 0) { // g_sprintf(text, "ok\r\n"); // g_file_write(fd, text, g_strlen(text)); SetServiceStatus(g_ssh, &g_service_status); g_listen = xrdp_listen_create(); xrdp_listen_main_loop(g_listen); g_sleep(100); g_service_status.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(g_ssh, &g_service_status); } else { //g_sprintf(text, "RegisterServiceCtrlHandler failed\r\n"); //g_file_write(fd, text, g_strlen(text)); } xrdp_listen_delete(g_listen); tc_mutex_delete(g_sync_mutex); tc_mutex_delete(g_sync1_mutex); g_destroy_wait_obj(g_term_event); g_destroy_wait_obj(g_sync_event); WSACleanup(); //CloseHandle(event_han); }
int DEFAULT_CC env_set_user(char *username, char *passwd_file, int display) { int error; int pw_uid; int pw_gid; int uid; char pw_shell[256]; char pw_dir[256]; char pw_gecos[256]; char text[256]; error = g_getuser_info(username, &pw_gid, &pw_uid, pw_shell, pw_dir, pw_gecos); if (error == 0) { g_rm_temp_dir(); error = g_setgid(pw_gid); if (error == 0) { error = g_initgroups(username, pw_gid); } if (error == 0) { uid = pw_uid; error = g_setuid(uid); } g_mk_temp_dir(0); if (error == 0) { g_clearenv(); g_setenv("SHELL", pw_shell, 1); g_setenv("PATH", "/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin", 1); g_setenv("USER", username, 1); g_sprintf(text, "%d", uid); g_setenv("UID", text, 1); g_setenv("HOME", pw_dir, 1); g_set_current_dir(pw_dir); g_sprintf(text, ":%d.0", display); g_setenv("DISPLAY", text, 1); g_setenv("LANG", "en_US.UTF-8", 1); if (passwd_file != 0) { if (0 == g_cfg->auth_file_path) { /* if no auth_file_path is set, then we go for $HOME/.vnc/sesman_username_passwd */ g_mkdir(".vnc"); g_sprintf(passwd_file, "%s/.vnc/sesman_%s_passwd", pw_dir, username); } else { /* we use auth_file_path as requested */ g_sprintf(passwd_file, g_cfg->auth_file_path, username); } LOG_DBG("pass file: %s", passwd_file); } } } else { log_message(LOG_LEVEL_ERROR, "error getting user info for user %s", username); } return error; }