settings.c (19459B)
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20#include "config.h" 21 22#include "argv.h" 23#include "common/defaults.h" 24#include "settings.h" 25#include "terminal/terminal.h" 26 27#include <guacamole/mem.h> 28#include <guacamole/user.h> 29#include <guacamole/wol-constants.h> 30 31#include <sys/types.h> 32#include <regex.h> 33#include <stdlib.h> 34#include <string.h> 35#include <time.h> 36 37/* Client plugin arguments */ 38const char* GUAC_TELNET_CLIENT_ARGS[] = { 39 "hostname", 40 "port", 41 "username", 42 "username-regex", 43 "password", 44 "password-regex", 45 GUAC_TELNET_ARGV_FONT_NAME, 46 GUAC_TELNET_ARGV_FONT_SIZE, 47 GUAC_TELNET_ARGV_COLOR_SCHEME, 48 "typescript-path", 49 "typescript-name", 50 "create-typescript-path", 51 "recording-path", 52 "recording-name", 53 "recording-exclude-output", 54 "recording-exclude-mouse", 55 "recording-include-keys", 56 "create-recording-path", 57 "read-only", 58 "backspace", 59 "terminal-type", 60 "scrollback", 61 "login-success-regex", 62 "login-failure-regex", 63 "disable-copy", 64 "disable-paste", 65 "wol-send-packet", 66 "wol-mac-addr", 67 "wol-broadcast-addr", 68 "wol-udp-port", 69 "wol-wait-time", 70 NULL 71}; 72 73enum TELNET_ARGS_IDX { 74 75 /** 76 * The hostname to connect to. Required. 77 */ 78 IDX_HOSTNAME, 79 80 /** 81 * The port to connect to. Optional. 82 */ 83 IDX_PORT, 84 85 /** 86 * The name of the user to login as. Optional. 87 */ 88 IDX_USERNAME, 89 90 /** 91 * The regular expression to use when searching for the username/login 92 * prompt. Optional. 93 */ 94 IDX_USERNAME_REGEX, 95 96 /** 97 * The password to use when logging in. Optional. 98 */ 99 IDX_PASSWORD, 100 101 /** 102 * The regular expression to use when searching for the password prompt. 103 * Optional. 104 */ 105 IDX_PASSWORD_REGEX, 106 107 /** 108 * The name of the font to use within the terminal. 109 */ 110 IDX_FONT_NAME, 111 112 /** 113 * The size of the font to use within the terminal, in points. 114 */ 115 IDX_FONT_SIZE, 116 117 /** 118 * The color scheme to use, as a series of semicolon-separated color-value 119 * pairs: "background: <color>", "foreground: <color>", or 120 * "color<n>: <color>", where <n> is a number from 0 to 255, and <color> is 121 * "color<n>" or an X11 color code (e.g. "aqua" or "rgb:12/34/56"). 122 * The color scheme can also be one of the special values: "black-white", 123 * "white-black", "gray-black", or "green-black". 124 */ 125 IDX_COLOR_SCHEME, 126 127 /** 128 * The full absolute path to the directory in which typescripts should be 129 * written. 130 */ 131 IDX_TYPESCRIPT_PATH, 132 133 /** 134 * The name that should be given to typescripts which are written in the 135 * given path. Each typescript will consist of two files: "NAME" and 136 * "NAME.timing". 137 */ 138 IDX_TYPESCRIPT_NAME, 139 140 /** 141 * Whether the specified typescript path should automatically be created 142 * if it does not yet exist. 143 */ 144 IDX_CREATE_TYPESCRIPT_PATH, 145 146 /** 147 * The full absolute path to the directory in which screen recordings 148 * should be written. 149 */ 150 IDX_RECORDING_PATH, 151 152 /** 153 * The name that should be given to screen recordings which are written in 154 * the given path. 155 */ 156 IDX_RECORDING_NAME, 157 158 /** 159 * Whether output which is broadcast to each connected client (graphics, 160 * streams, etc.) should NOT be included in the session recording. Output 161 * is included by default, as it is necessary for any recording which must 162 * later be viewable as video. 163 */ 164 IDX_RECORDING_EXCLUDE_OUTPUT, 165 166 /** 167 * Whether changes to mouse state, such as position and buttons pressed or 168 * released, should NOT be included in the session recording. Mouse state 169 * is included by default, as it is necessary for the mouse cursor to be 170 * rendered in any resulting video. 171 */ 172 IDX_RECORDING_EXCLUDE_MOUSE, 173 174 /** 175 * Whether keys pressed and released should be included in the session 176 * recording. Key events are NOT included by default within the recording, 177 * as doing so has privacy and security implications. Including key events 178 * may be necessary in certain auditing contexts, but should only be done 179 * with caution. Key events can easily contain sensitive information, such 180 * as passwords, credit card numbers, etc. 181 */ 182 IDX_RECORDING_INCLUDE_KEYS, 183 184 /** 185 * Whether the specified screen recording path should automatically be 186 * created if it does not yet exist. 187 */ 188 IDX_CREATE_RECORDING_PATH, 189 190 /** 191 * "true" if this connection should be read-only (user input should be 192 * dropped), "false" or blank otherwise. 193 */ 194 IDX_READ_ONLY, 195 196 /** 197 * ASCII code, as an integer to use for the backspace key, or 198 * GUAC_TERMINAL_DEFAULT_BACKSPACE if not specified. 199 */ 200 IDX_BACKSPACE, 201 202 /** 203 * The terminal emulator type that is passed to the remote system (e.g. 204 * "xterm" or "xterm-256color"). "linux" is used if unspecified. 205 */ 206 IDX_TERMINAL_TYPE, 207 208 /** 209 * The maximum size of the scrollback buffer in rows. 210 */ 211 IDX_SCROLLBACK, 212 213 /** 214 * The regular expression to use when searching for whether login was 215 * successful. This parameter is optional. If given, the 216 * "login-failure-regex" parameter must also be specified, and the first 217 * frame of the Guacamole connection will be withheld until login 218 * success/failure has been determined. 219 */ 220 IDX_LOGIN_SUCCESS_REGEX, 221 222 /** 223 * The regular expression to use when searching for whether login was 224 * unsuccessful. This parameter is optional. If given, the 225 * "login-success-regex" parameter must also be specified, and the first 226 * frame of the Guacamole connection will be withheld until login 227 * success/failure has been determined. 228 */ 229 IDX_LOGIN_FAILURE_REGEX, 230 231 /** 232 * Whether outbound clipboard access should be blocked. If set to "true", 233 * it will not be possible to copy data from the terminal to the client 234 * using the clipboard. By default, clipboard access is not blocked. 235 */ 236 IDX_DISABLE_COPY, 237 238 /** 239 * Whether inbound clipboard access should be blocked. If set to "true", it 240 * will not be possible to paste data from the client to the terminal using 241 * the clipboard. By default, clipboard access is not blocked. 242 */ 243 IDX_DISABLE_PASTE, 244 245 /** 246 * Whether to send the magic Wake-on-LAN (WoL) packet. If set to "true" 247 * the WoL packet will be sent prior to attempting to connect to the remote 248 * host. By default the WoL packet will not be sent. 249 */ 250 IDX_WOL_SEND_PACKET, 251 252 /** 253 * The MAC address to put in the magic WoL packet to wake the remote host. 254 * There is no default value, and if WoL is enabled but the MAC address 255 * is not provided, a warning will be logged and no packet will be sent. 256 */ 257 IDX_WOL_MAC_ADDR, 258 259 /** 260 * The broadcast address to which to send the magic WoL packet. 261 */ 262 IDX_WOL_BROADCAST_ADDR, 263 264 /** 265 * The UDP port to use when sending the WoL packet. 266 */ 267 IDX_WOL_UDP_PORT, 268 269 /** 270 * The amount of time, in seconds, to wait after the magic WoL packet is 271 * sent before continuing the connection attempt. The default is not to 272 * wait at all (0 seconds). 273 */ 274 IDX_WOL_WAIT_TIME, 275 276 TELNET_ARGS_COUNT 277}; 278 279/** 280 * Compiles the given regular expression, returning NULL if compilation fails 281 * or of the given regular expression is NULL. The returned regex_t must be 282 * freed with regfree() AND guac_mem_free(), or with guac_telnet_regex_free(). 283 * 284 * @param user 285 * The user who provided the setting associated with the given regex 286 * pattern. Error messages will be logged on behalf of this user. 287 * 288 * @param pattern 289 * The regular expression pattern to compile. 290 * 291 * @return 292 * The compiled regular expression, or NULL if compilation fails or NULL 293 * was originally provided for the pattern. 294 */ 295static regex_t* guac_telnet_compile_regex(guac_user* user, char* pattern) { 296 297 /* Nothing to compile if no pattern provided */ 298 if (pattern == NULL) 299 return NULL; 300 301 int compile_result; 302 regex_t* regex = guac_mem_alloc(sizeof(regex_t)); 303 304 /* Compile regular expression */ 305 compile_result = regcomp(regex, pattern, 306 REG_EXTENDED | REG_NOSUB | REG_ICASE | REG_NEWLINE); 307 308 /* Notify of failure to parse/compile */ 309 if (compile_result != 0) { 310 guac_user_log(user, GUAC_LOG_ERROR, "Regular expression '%s' " 311 "could not be compiled.", pattern); 312 guac_mem_free(regex); 313 return NULL; 314 } 315 316 return regex; 317} 318 319void guac_telnet_regex_free(regex_t** regex) { 320 if (*regex != NULL) { 321 regfree(*regex); 322 guac_mem_free(*regex); 323 *regex = NULL; 324 } 325} 326 327guac_telnet_settings* guac_telnet_parse_args(guac_user* user, 328 int argc, const char** argv) { 329 330 /* Validate arg count */ 331 if (argc != TELNET_ARGS_COUNT) { 332 guac_user_log(user, GUAC_LOG_WARNING, "Incorrect number of connection " 333 "parameters provided: expected %i, got %i.", 334 TELNET_ARGS_COUNT, argc); 335 return NULL; 336 } 337 338 guac_telnet_settings* settings = guac_mem_zalloc(sizeof(guac_telnet_settings)); 339 340 /* Read parameters */ 341 settings->hostname = 342 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 343 IDX_HOSTNAME, ""); 344 345 /* Read username */ 346 settings->username = 347 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 348 IDX_USERNAME, NULL); 349 350 /* Read username regex only if username is specified */ 351 if (settings->username != NULL) { 352 settings->username_regex = guac_telnet_compile_regex(user, 353 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 354 IDX_USERNAME_REGEX, GUAC_TELNET_DEFAULT_USERNAME_REGEX)); 355 } 356 357 /* Read password */ 358 settings->password = 359 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 360 IDX_PASSWORD, NULL); 361 362 /* Read password regex only if password is specified */ 363 if (settings->password != NULL) { 364 settings->password_regex = guac_telnet_compile_regex(user, 365 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 366 IDX_PASSWORD_REGEX, GUAC_TELNET_DEFAULT_PASSWORD_REGEX)); 367 } 368 369 /* Read optional login success detection regex */ 370 settings->login_success_regex = guac_telnet_compile_regex(user, 371 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 372 IDX_LOGIN_SUCCESS_REGEX, NULL)); 373 374 /* Read optional login failure detection regex */ 375 settings->login_failure_regex = guac_telnet_compile_regex(user, 376 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 377 IDX_LOGIN_FAILURE_REGEX, NULL)); 378 379 /* Both login success and login failure regexes must be provided if either 380 * is present at all */ 381 if (settings->login_success_regex != NULL 382 && settings->login_failure_regex == NULL) { 383 guac_telnet_regex_free(&settings->login_success_regex); 384 guac_user_log(user, GUAC_LOG_WARNING, "Ignoring provided value for " 385 "\"%s\" as \"%s\" must also be provided.", 386 GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_SUCCESS_REGEX], 387 GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_FAILURE_REGEX]); 388 } 389 else if (settings->login_failure_regex != NULL 390 && settings->login_success_regex == NULL) { 391 guac_telnet_regex_free(&settings->login_failure_regex); 392 guac_user_log(user, GUAC_LOG_WARNING, "Ignoring provided value for " 393 "\"%s\" as \"%s\" must also be provided.", 394 GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_FAILURE_REGEX], 395 GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_SUCCESS_REGEX]); 396 } 397 398 /* Read-only mode */ 399 settings->read_only = 400 guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, 401 IDX_READ_ONLY, false); 402 403 /* Read maximum scrollback size */ 404 settings->max_scrollback = 405 guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv, 406 IDX_SCROLLBACK, GUAC_TERMINAL_DEFAULT_MAX_SCROLLBACK); 407 408 /* Read font name */ 409 settings->font_name = 410 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 411 IDX_FONT_NAME, GUAC_TERMINAL_DEFAULT_FONT_NAME); 412 413 /* Read font size */ 414 settings->font_size = 415 guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv, 416 IDX_FONT_SIZE, GUAC_TERMINAL_DEFAULT_FONT_SIZE); 417 418 /* Copy requested color scheme */ 419 settings->color_scheme = 420 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 421 IDX_COLOR_SCHEME, GUAC_TERMINAL_DEFAULT_COLOR_SCHEME); 422 423 /* Pull width/height/resolution directly from user */ 424 settings->width = user->info.optimal_width; 425 settings->height = user->info.optimal_height; 426 settings->resolution = user->info.optimal_resolution; 427 428 /* Read port */ 429 settings->port = 430 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 431 IDX_PORT, GUAC_TELNET_DEFAULT_PORT); 432 433 /* Read typescript path */ 434 settings->typescript_path = 435 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 436 IDX_TYPESCRIPT_PATH, NULL); 437 438 /* Read typescript name */ 439 settings->typescript_name = 440 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 441 IDX_TYPESCRIPT_NAME, GUAC_TELNET_DEFAULT_TYPESCRIPT_NAME); 442 443 /* Parse path creation flag */ 444 settings->create_typescript_path = 445 guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, 446 IDX_CREATE_TYPESCRIPT_PATH, false); 447 448 /* Read recording path */ 449 settings->recording_path = 450 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 451 IDX_RECORDING_PATH, NULL); 452 453 /* Read recording name */ 454 settings->recording_name = 455 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 456 IDX_RECORDING_NAME, GUAC_TELNET_DEFAULT_RECORDING_NAME); 457 458 /* Parse output exclusion flag */ 459 settings->recording_exclude_output = 460 guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, 461 IDX_RECORDING_EXCLUDE_OUTPUT, false); 462 463 /* Parse mouse exclusion flag */ 464 settings->recording_exclude_mouse = 465 guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, 466 IDX_RECORDING_EXCLUDE_MOUSE, false); 467 468 /* Parse key event inclusion flag */ 469 settings->recording_include_keys = 470 guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, 471 IDX_RECORDING_INCLUDE_KEYS, false); 472 473 /* Parse path creation flag */ 474 settings->create_recording_path = 475 guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, 476 IDX_CREATE_RECORDING_PATH, false); 477 478 /* Parse backspace key code */ 479 settings->backspace = 480 guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv, 481 IDX_BACKSPACE, GUAC_TERMINAL_DEFAULT_BACKSPACE); 482 483 /* Read terminal emulator type. */ 484 settings->terminal_type = 485 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 486 IDX_TERMINAL_TYPE, "linux"); 487 488 /* Parse clipboard copy disable flag */ 489 settings->disable_copy = 490 guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, 491 IDX_DISABLE_COPY, false); 492 493 /* Parse clipboard paste disable flag */ 494 settings->disable_paste = 495 guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, 496 IDX_DISABLE_PASTE, false); 497 498 /* Parse Wake-on-LAN (WoL) settings */ 499 settings->wol_send_packet = 500 guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, 501 IDX_WOL_SEND_PACKET, false); 502 503 if (settings->wol_send_packet) { 504 505 /* If WoL has been enabled but no MAC provided, log warning and disable. */ 506 if(strcmp(argv[IDX_WOL_MAC_ADDR], "") == 0) { 507 guac_user_log(user, GUAC_LOG_WARNING, "Wake on LAN was requested, ", 508 "but no MAC address was specified. WoL will not be sent."); 509 settings->wol_send_packet = false; 510 } 511 512 /* Parse the WoL MAC address. */ 513 settings->wol_mac_addr = 514 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 515 IDX_WOL_MAC_ADDR, NULL); 516 517 /* Parse the WoL broadcast address. */ 518 settings->wol_broadcast_addr = 519 guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, 520 IDX_WOL_BROADCAST_ADDR, GUAC_WOL_LOCAL_IPV4_BROADCAST); 521 522 /* Parse the WoL broadcast port. */ 523 settings->wol_udp_port = (unsigned short) 524 guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv, 525 IDX_WOL_UDP_PORT, GUAC_WOL_PORT); 526 527 /* Parse the WoL wait time. */ 528 settings->wol_wait_time = 529 guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv, 530 IDX_WOL_WAIT_TIME, GUAC_WOL_DEFAULT_BOOT_WAIT_TIME); 531 532 } 533 534 /* Parsing was successful */ 535 return settings; 536 537} 538 539void guac_telnet_settings_free(guac_telnet_settings* settings) { 540 541 /* Free network connection information */ 542 guac_mem_free(settings->hostname); 543 guac_mem_free(settings->port); 544 545 /* Free credentials */ 546 guac_mem_free(settings->username); 547 guac_mem_free(settings->password); 548 549 /* Free various regexes */ 550 guac_telnet_regex_free(&settings->username_regex); 551 guac_telnet_regex_free(&settings->password_regex); 552 guac_telnet_regex_free(&settings->login_success_regex); 553 guac_telnet_regex_free(&settings->login_failure_regex); 554 555 /* Free display preferences */ 556 guac_mem_free(settings->font_name); 557 guac_mem_free(settings->color_scheme); 558 559 /* Free typescript settings */ 560 guac_mem_free(settings->typescript_name); 561 guac_mem_free(settings->typescript_path); 562 563 /* Free screen recording settings */ 564 guac_mem_free(settings->recording_name); 565 guac_mem_free(settings->recording_path); 566 567 /* Free terminal emulator type. */ 568 guac_mem_free(settings->terminal_type); 569 570 /* Free WoL settings. */ 571 guac_mem_free(settings->wol_mac_addr); 572 guac_mem_free(settings->wol_broadcast_addr); 573 574 /* Free overall structure */ 575 guac_mem_free(settings); 576 577} 578