diff --git a/docs/man/xrdp-sesadmin.8.in b/docs/man/xrdp-sesadmin.8.in index 6727772b..953f3f67 100644 --- a/docs/man/xrdp-sesadmin.8.in +++ b/docs/man/xrdp-sesadmin.8.in @@ -18,13 +18,11 @@ command. A summary of options is included below. .TP .BI \-u= username -\fIUsername\fP for authentication on the server. -Defaults to \fBroot\fP. +Retained for compatibility, but ignored. .TP .BI \-p= password -The \fIpassword\fP to authenticate with. -The default is to ask for the password interactively. +Retained for compatibility, but ignored. .TP .BI \-i= port @@ -39,7 +37,7 @@ Valid commands are: .RS 4 .TP .B list -List currently active sessions. +List active sessions for the current user. .TP .BI kill: sid Kills the session specified the given \fIsession id\fP. diff --git a/docs/man/xrdp-sesrun.8.in b/docs/man/xrdp-sesrun.8.in index 256c4f7a..96585ece 100644 --- a/docs/man/xrdp-sesrun.8.in +++ b/docs/man/xrdp-sesrun.8.in @@ -4,18 +4,28 @@ .SH "SYNTAX" .B xrdp\-sesrun -.I [ options ] username +.I --help +.br + +.B xrdp\-sesrun +.I [ options ] [ username ] .SH "DESCRIPTION" \fBxrdp\-sesrun\fR starts a session using \fBxrdp\-sesman\fR(8). .br -This is a tool useful for testing, it simply behaves like xrdp when some +This is a tool useful for testing. It simply behaves like xrdp when some user logs in a new session and authenticates, thus starting a new session. -Default values for the options are set at compile-time. Run the utility without -a username to see what the defaults are for your installation. +Default values for the options are set at compile-time. Run the utility with +the '--help' option to see what the defaults are for your installation. -The utility prompts for a password if neither \fB-p\fR or \fB-F\fR is used. +If no username is used, the current username is used, and no password +needs to be provided. In this instance, it is important that any necessary +authentication tokens for a GUI session (e.g. a Kerberos ticket) have +already been acquired. + +If a username is provided, a password must also be provided. In this instance +the utility prompts for a password if neither \fB-p\fR or \fB-F\fR is used. .SH "OPTIONS" .TP @@ -60,6 +70,10 @@ Override the default logging level. One of "error", "warn", "info", .SH "EXAMPLES" .TP .B +xrdp-sesrun +Create a default session for the current user. +.TP +.B xrdp-sesrun -F 0 user1 #include -char user[257]; -char pass[257]; char cmnd[257]; char port[257]; @@ -47,12 +45,9 @@ int main(int argc, char **argv) //int end; int idx; //int sel; - char *pwd; struct log_config *logging; int rv = 1; - user[0] = '\0'; - pass[0] = '\0'; cmnd[0] = '\0'; port[0] = '\0'; @@ -64,11 +59,11 @@ int main(int argc, char **argv) { if (0 == g_strncmp(argv[idx], "-u=", 3)) { - g_strncpy(user, (argv[idx]) + 3, 256); + g_printf("** Ignoring unused argument '-u'"); } else if (0 == g_strncmp(argv[idx], "-p=", 3)) { - g_strncpy(pass, (argv[idx]) + 3, 256); + g_printf("** Ignoring unused argument '-p'"); } else if (0 == g_strncmp(argv[idx], "-i=", 3)) { @@ -80,48 +75,57 @@ int main(int argc, char **argv) } } - if (0 == g_strncmp(port, "", 1)) - { - g_strncpy(port, "3350", 256); - } - - if (0 == g_strncmp(user, "", 1)) - { - cmndHelp(); - return 0; - } - if (0 == g_strncmp(cmnd, "", 1)) { cmndHelp(); return 0; } - if (0 == g_strncmp(pass, "", 1)) - { - pwd = getpass("password:"); - g_strncpy(pass, pwd, 256); - - } - - t = scp_connect(port, NULL); - + t = scp_connect(port, "xrdp-sesadmin", NULL); if (t == NULL) { LOG(LOG_LEVEL_ERROR, "scp_connect() error"); } - else if (0 == g_strncmp(cmnd, "list", 5)) + else { - rv = cmndList(t); - } - else if (0 == g_strncmp(cmnd, "kill:", 5)) - { - rv = cmndKill(t); + enum scp_login_status login_result; + + /* Log in as the current user */ + if ((rv = scp_send_uds_login_request(t)) == 0 && + (rv = wait_for_sesman_reply(t, E_SCP_LOGIN_RESPONSE)) == 0) + { + rv = scp_get_login_response(t, &login_result, NULL); + if (rv == 0) + { + if (login_result != E_SCP_LOGIN_OK) + { + char msg[256]; + scp_login_status_to_str(login_result, msg, sizeof(msg)); + g_printf("Login failed; %s\n", msg); + rv = 1; + } + } + scp_msg_in_reset(t); // Done with this message + } } - g_memset(pass, '\0', sizeof(pass)); + if (rv == 0) + { + if (0 == g_strncmp(cmnd, "list", 5)) + { + rv = cmndList(t); + } + else if (0 == g_strncmp(cmnd, "kill:", 5)) + { + rv = cmndKill(t); + } + } + if (rv == 0) + { + rv = scp_send_close_connection_request(t); + } trans_delete(t); log_end(); @@ -133,10 +137,7 @@ cmndHelp(void) { fprintf(stderr, "sesadmin - a console sesman administration tool\n"); fprintf(stderr, "syntax: sesadmin [] COMMAND [OPTIONS]\n\n"); - fprintf(stderr, "-u=: username to connect to sesman [MANDATORY]\n"); - fprintf(stderr, "-p=: password to connect to sesman (asked if not given)\n"); - fprintf(stderr, "-s=: sesman host (default is localhost)\n"); - fprintf(stderr, "-i= : sesman port (default 3350)\n"); + fprintf(stderr, "-i= : sesman port (can be defaulted)\n"); fprintf(stderr, "-c= : command to execute on the server [MANDATORY]\n"); fprintf(stderr, " it can be one of those:\n"); fprintf(stderr, " list\n"); @@ -146,9 +147,14 @@ cmndHelp(void) static void print_session(const struct scp_session_info *s) { + char *username; + const char *uptr; + g_getuser_info_by_uid(s->uid, &username, NULL, NULL, NULL, NULL); + uptr = (username == NULL) ? "" : username; + printf("Session ID: %d\n", s->sid); printf("\tDisplay: :%u\n", s->display); - printf("\tUser: %s\n", s->username); + printf("\tUser: %s\n", uptr); printf("\tSession type: %s\n", SCP_SESSION_TYPE_TO_STR(s->type)); printf("\tScreen size: %dx%d, color depth %d\n", s->width, s->height, s->bpp); @@ -157,6 +163,7 @@ print_session(const struct scp_session_info *s) { printf("\tStart IP address: %s\n", s->start_ip_addr); } + g_free(username); } static int @@ -168,7 +175,7 @@ cmndList(struct trans *t) enum scp_list_sessions_status status; struct scp_session_info *p; - int rv = scp_send_list_sessions_request(t, user, pass); + int rv = scp_send_list_sessions_request(t); sessions->auto_free = 1; @@ -188,11 +195,6 @@ cmndList(struct trans *t) switch (status) { - case E_SCP_LS_AUTHENTICATION_FAIL: - printf("Connection denied (authentication error)\n"); - rv = 1; - break; - case E_SCP_LS_SESSION_INFO: list_add_item(sessions, (tintptr)p); break; diff --git a/sesman/tools/sesrun.c b/sesman/tools/sesrun.c index b785f5d0..dc2d0c82 100644 --- a/sesman/tools/sesrun.c +++ b/sesman/tools/sesrun.c @@ -94,7 +94,7 @@ struct session_params const char *directory; const char *shell; - const char *connection_description; + const char *ip_addr; const char *username; char password[MAX_PASSWORD_LEN + 1]; @@ -165,7 +165,9 @@ usage(void) g_printf("xrdp session starter v" PACKAGE_VERSION "\n"); g_printf("\nusage:\n"); - g_printf("sesrun [options] username\n\n"); + g_printf("sesrun --help\n" + "\nor\n" + "sesrun [options] [username]\n\n"); g_printf("options:\n"); g_printf(" -g Default:%dx%d\n", DEFAULT_WIDTH, DEFAULT_HEIGHT); @@ -176,9 +178,11 @@ usage(void) " -p TESTING ONLY - DO NOT USE IN PRODUCTION\n" " -F Read password from this file descriptor\n" " -c Alternative sesman.ini file\n"); - g_printf("Supported types are %s\n", + g_printf("\nSupported types are %s\n", sesstype_list); - g_printf("Password is prompted if -p or -F are not specified\n"); + g_printf("\nIf username is omitted, the current user is used.\n" + "If username is provided, password is needed.\n" + " Password is prompted for if -p or -F are not specified\n"); } @@ -286,7 +290,7 @@ parse_program_args(int argc, char *argv[], struct session_params *sp, sp->directory = ""; sp->shell = ""; - sp->connection_description = ""; + sp->ip_addr = ""; sp->username = NULL; sp->password[0] = '\0'; @@ -367,33 +371,109 @@ parse_program_args(int argc, char *argv[], struct session_params *sp, } } - if (argc <= optind) + if (argc == optind) { - LOG(LOG_LEVEL_ERROR, "No user name specified"); - params_ok = 0; + // No username was specified + if (password_set) + { + LOG(LOG_LEVEL_WARNING, "No username - ignoring specified password"); + sp->password[0] = '\0'; + } + sp->username = NULL; } else if ((argc - optind) > 1) { LOG(LOG_LEVEL_ERROR, "Unexpected arguments after username"); params_ok = 0; } - else + else if (params_ok) { + // A username is specified sp->username = argv[optind]; - } - - if (params_ok && !password_set) - { - const char *p = getpass("Password: "); - if (p != NULL) + if (!password_set) { - g_strcpy(sp->password, p); + const char *p = getpass("Password: "); + if (p == NULL) + { + params_ok = 0; + } + else + { + g_snprintf(sp->password, sizeof(sp->password), "%s", p); + } } } return params_ok; } +/**************************************************************************//** + * Sends an SCP login request + * + * A sys login request (i.e. username / password) is used if a username + * is specified. Otherwise we use a uds login request for the current user. + * + * @param t SCP connection + * @param sp Data for request + */ +static int +send_login_request(struct trans *t, const struct session_params *sp) +{ + int rv; + LOG(LOG_LEVEL_DEBUG, "ip_addr:\"%s\"", sp->ip_addr); + if (sp->username != NULL) + { + /* Only log the password in development builds */ + LOG_DEVEL(LOG_LEVEL_DEBUG, "password:\"%s\"", sp->password); + + rv = scp_send_sys_login_request(t, sp->username, + sp->password, sp->ip_addr); + } + else + { + rv = scp_send_uds_login_request(t); + } + + return rv; +} + +/**************************************************************************//** + * Receives an SCP login response + * + * @param t SCP transport to receive reply on + * @param[out] server_closed != 0 if server has gone away + * @return 0 for successful authentication + */ +static int +handle_login_response(struct trans *t, int *server_closed) +{ + enum scp_login_status login_result; + + int rv = wait_for_sesman_reply(t, E_SCP_LOGIN_RESPONSE); + if (rv != 0) + { + *server_closed = 1; + } + else + { + rv = scp_get_login_response(t, &login_result, server_closed); + if (rv == 0) + { + if (login_result != E_SCP_LOGIN_OK) + { + char msg[256]; + scp_login_status_to_str(login_result, msg, sizeof(msg)); + g_printf("Login failed; %s\n", msg); + rv = 1; + } + } + scp_msg_in_reset(t); // Done with this message + } + + return rv; +} + + /**************************************************************************//** * Sends an SCP create session request * @@ -405,18 +485,13 @@ send_create_session_request(struct trans *t, const struct session_params *sp) { LOG(LOG_LEVEL_DEBUG, "width:%d height:%d bpp:%d code:%d\n" - "directory:\"%s\"\n" - "shell:\"%s\" connection_description:\"%s\"", + "directory:\"%s\" shell:\"%s\"", sp->width, sp->height, sp->bpp, sp->session_type, - sp->directory, - sp->shell, sp->connection_description); - /* Only log the password in development builds */ - LOG_DEVEL(LOG_LEVEL_DEBUG, "password:\"%s\"", sp->password); + sp->directory, sp->shell); return scp_send_create_session_request( - t, sp->username, sp->password, sp->session_type, - sp->width, sp->height, sp->bpp, sp->shell, sp->directory, - sp->connection_description); + t, sp->session_type, + sp->width, sp->height, sp->bpp, sp->shell, sp->directory); } /**************************************************************************//** @@ -428,21 +503,24 @@ send_create_session_request(struct trans *t, const struct session_params *sp) static int handle_create_session_response(struct trans *t) { - int auth_result; + enum scp_screate_status status; int display; struct guid guid; int rv = wait_for_sesman_reply(t, E_SCP_CREATE_SESSION_RESPONSE); if (rv == 0) { - rv = scp_get_create_session_response(t, &auth_result, + rv = scp_get_create_session_response(t, &status, &display, &guid); if (rv == 0) { - if (auth_result != 0) + if (status != E_SCP_SCREATE_OK) { - g_printf("Connection denied (authentication error)\n"); + char msg[256]; + scp_screate_status_to_str(status, msg, sizeof(msg)); + g_printf("Connection failed; %s\n", msg); + rv = 1; } else { @@ -452,6 +530,7 @@ handle_create_session_response(struct trans *t) guid_to_str(&guid, guid_str)); } } + scp_msg_in_reset(t); // Done with this message } return rv; @@ -475,7 +554,12 @@ main(int argc, char **argv) log_start_from_param(logging); log_config_free(logging); - if (!parse_program_args(argc, argv, &sp, &sesman_ini)) + if (argc == 2 && g_strcmp(argv[1], "--help") == 0) + { + usage(); + rv = 0; + } + else if (!parse_program_args(argc, argv, &sp, &sesman_ini)) { usage(); } @@ -484,20 +568,44 @@ main(int argc, char **argv) LOG(LOG_LEVEL_ERROR, "error reading config file %s : %s", sesman_ini, g_get_strerror()); } - else if (!(t = scp_connect(cfg->listen_port, NULL))) + else if (!(t = scp_connect(cfg->listen_port, "xrdp-sesrun", NULL))) { LOG(LOG_LEVEL_ERROR, "connect error - %s", g_get_strerror()); } else { - rv = send_create_session_request(t, &sp); - if (rv != 0) + int server_closed = 0; + while (!server_closed) { - LOG(LOG_LEVEL_ERROR, "Error sending create session to sesman"); + rv = send_login_request(t, &sp); + if (rv != 0) + { + LOG(LOG_LEVEL_ERROR, "Error sending login request to sesman"); + break; + } + + rv = handle_login_response(t, &server_closed); + if (rv == 0) + { + break; /* Successful authentication */ + } + if (!server_closed) + { + const char *p = getpass("Password: "); + if (p == NULL) + { + break; + } + g_snprintf(sp.password, sizeof(sp.password), "%s", p); + } } - else + + if (rv == 0) { - rv = handle_create_session_response(t); + if ((rv = send_create_session_request(t, &sp)) == 0) + { + rv = handle_create_session_response(t); + } } trans_delete(t); }