case ARG_VERSION:
return version();
- case ARG_NO_PAGER:
- arg_pager_flags |= PAGER_DISABLE;
- break;
-
- case ARG_NO_LEGEND:
- arg_legend = false;
- break;
-
- case ARG_NO_ASK_PASSWORD:
- arg_ask_password = false;
- break;
-
case ARG_OFFLINE:
arg_offline = true;
break;
arg_identity = optarg;
break;
+ case ARG_JSON:
+ r = parse_json_argument(optarg, &arg_json_format_flags);
+ if (r <= 0)
+ return r;
+
+ break;
+
+ case 'j':
+ arg_json_format_flags = SD_JSON_FORMAT_PRETTY_AUTO|SD_JSON_FORMAT_COLOR_AUTO;
+ break;
+
+ case ARG_EXPORT_FORMAT:
+ if (streq(optarg, "help"))
+ return DUMP_STRING_TABLE(export_format, ExportFormat, _EXPORT_FORMAT_MAX);
+
+ arg_export_format = export_format_from_string(optarg);
+ if (arg_export_format < 0)
+ return log_error_errno(arg_export_format, "Invalid export format: %s", optarg);
+
+ break;
+
+ case 'E':
+ if (arg_export_format == EXPORT_FORMAT_FULL)
+ arg_export_format = EXPORT_FORMAT_STRIPPED;
+ else if (arg_export_format == EXPORT_FORMAT_STRIPPED)
+ arg_export_format = EXPORT_FORMAT_MINIMAL;
+ else
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specifying -E more than twice is not supported.");
+
+ arg_json_format_flags &= ~SD_JSON_FORMAT_OFF;
+ if (arg_json_format_flags == 0)
+ arg_json_format_flags = SD_JSON_FORMAT_PRETTY_AUTO|SD_JSON_FORMAT_COLOR_AUTO;
+ break;
+
+ case ARG_KEY_NAME:
+ if (!isempty(optarg) && !filename_is_valid(optarg))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Parameter for --key-name= not a valid filename: %s", optarg);
+
+ r = free_and_strdup_warn(&arg_key_name, empty_to_null(optarg));
+ if (r < 0)
+ return r;
+ break;
+
+ case ARG_SEIZE:
+ r = parse_boolean_argument("--seize=", optarg, &arg_seize);
+ if (r < 0)
+ return r;
+ break;
+
+ case ARG_PROMPT_NEW_USER:
+ arg_prompt_new_user = true;
+ break;
+
+ case ARG_PROMPT_GROUPS:
+ r = parse_boolean_argument("--prompt-groups=", optarg, &arg_prompt_groups);
+ if (r < 0)
+ return r;
+
+ break;
+
+ case ARG_PROMPT_SHELL:
+ r = parse_boolean_argument("--prompt-shell=", optarg, &arg_prompt_shell);
+ if (r < 0)
+ return r;
+
+ break;
+
+ case ARG_CHROME:
+ r = parse_boolean_argument("--chrome=", optarg, &arg_chrome);
+ if (r < 0)
+ return r;
+
+ break;
+
+ case ARG_MUTE_CONSOLE:
+ r = parse_boolean_argument("--mute-console=", optarg, &arg_mute_console);
+ if (r < 0)
+ return r;
+
+ break;
+
+ case ARG_NO_PAGER:
+ arg_pager_flags |= PAGER_DISABLE;
+ break;
+
+ case ARG_NO_LEGEND:
+ arg_legend = false;
+ break;
+
+ case ARG_NO_ASK_PASSWORD:
+ arg_ask_password = false;
+ break;
+
case 'c':
if (!isempty(optarg) && !valid_gecos(optarg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
return r;
break;
- case ARG_ALIAS:
- r = parse_group_field(&arg_identity_extra, "aliases", optarg);
+ case ARG_REALM:
+ r = parse_realm_field(&arg_identity_extra, "realm", optarg);
if (r < 0)
return r;
break;
- case 'd':
- r = parse_home_directory_field(&arg_identity_extra, "homeDirectory", optarg);
+ case ARG_ALIAS:
+ r = parse_group_field(&arg_identity_extra, "aliases", optarg);
if (r < 0)
return r;
break;
- case ARG_REALM:
- r = parse_realm_field(&arg_identity_extra, "realm", optarg);
+ case ARG_EMAIL_ADDRESS:
+ r = parse_string_field(match_identity ?: &arg_identity_extra, "emailAddress", optarg);
if (r < 0)
return r;
break;
- case ARG_EMAIL_ADDRESS:
case ARG_LOCATION:
- case ARG_ICON_NAME:
- case ARG_CIFS_USER_NAME:
- case ARG_CIFS_DOMAIN:
- case ARG_CIFS_EXTRA_MOUNT_OPTIONS:
- case ARG_LUKS_EXTRA_MOUNT_OPTIONS:
- case ARG_SESSION_LAUNCHER:
- case ARG_SESSION_TYPE: {
- const char *field =
- c == ARG_EMAIL_ADDRESS ? "emailAddress" :
- c == ARG_LOCATION ? "location" :
- c == ARG_ICON_NAME ? "iconName" :
- c == ARG_CIFS_USER_NAME ? "cifsUserName" :
- c == ARG_CIFS_DOMAIN ? "cifsDomain" :
- c == ARG_CIFS_EXTRA_MOUNT_OPTIONS ? "cifsExtraMountOptions" :
- c == ARG_LUKS_EXTRA_MOUNT_OPTIONS ? "luksExtraMountOptions" :
- c == ARG_SESSION_LAUNCHER ? "preferredSessionLauncher" :
- c == ARG_SESSION_TYPE ? "preferredSessionType" :
- NULL;
- assert(field);
-
- r = parse_string_field(match_identity ?: &arg_identity_extra, field, optarg);
+ r = parse_string_field(match_identity ?: &arg_identity_extra, "location", optarg);
if (r < 0)
return r;
break;
- }
case ARG_BIRTH_DATE:
if (isempty(optarg)) {
}
break;
- case ARG_CIFS_SERVICE:
- if (!isempty(optarg)) {
- r = parse_cifs_service(optarg, /* ret_host= */ NULL, /* ret_service= */ NULL, /* ret_path= */ NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to validate CIFS service name: %s", optarg);
- }
+ case ARG_ICON_NAME:
+ r = parse_string_field(match_identity ?: &arg_identity_extra, "iconName", optarg);
+ if (r < 0)
+ return r;
+ break;
- r = parse_string_field(match_identity ?: &arg_identity_extra, "cifsService", optarg);
+ case 'd':
+ r = parse_home_directory_field(&arg_identity_extra, "homeDirectory", optarg);
if (r < 0)
return r;
break;
- case ARG_PASSWORD_HINT:
- r = parse_string_field(&arg_identity_extra_privileged, "passwordHint", optarg);
+ case 'u':
+ r = parse_uid_field(&arg_identity_extra, "uid", optarg);
if (r < 0)
return r;
+ break;
- string_erase(optarg);
+ case 'G':
+ r = parse_group_field(match_identity ?: &arg_identity_extra, "memberOf", optarg);
+ if (r < 0)
+ return r;
break;
- case ARG_NICE:
- r = parse_nice_field(match_identity ?: &arg_identity_extra, "niceLevel", optarg);
+ case ARG_CAPABILITY_BOUNDING_SET:
+ r = parse_capability_set_field(match_identity ?: &arg_identity_extra,
+ &arg_capability_bounding_set,
+ "capabilityBoundingSet", optarg);
if (r < 0)
return r;
break;
- case ARG_RLIMIT:
- r = parse_rlimit_field(&arg_identity_extra_rlimits, "resourceLimits", optarg);
+ case ARG_CAPABILITY_AMBIENT_SET:
+ r = parse_capability_set_field(match_identity ?: &arg_identity_extra,
+ &arg_capability_ambient_set,
+ "capabilityAmbientSet", optarg);
if (r < 0)
return r;
break;
- case 'u':
- r = parse_uid_field(&arg_identity_extra, "uid", optarg);
+ case ARG_ACCESS_MODE:
+ r = parse_mode_field(&arg_identity_extra, "accessMode", optarg);
if (r < 0)
return r;
break;
- case 'k':
- case ARG_IMAGE_PATH: {
- const char *field = c == 'k' ? "skeletonDirectory" : "imagePath";
+ case ARG_UMASK:
+ r = parse_mode_field(match_identity ?: &arg_identity_extra, "umask", optarg);
+ if (r < 0)
+ return r;
+ break;
- r = parse_path_field(match_identity ?: &arg_identity_extra_this_machine, field, optarg);
+ case 'k':
+ r = parse_path_field(match_identity ?: &arg_identity_extra_this_machine, "skeletonDirectory", optarg);
if (r < 0)
return r;
break;
- }
case 's':
if (!isempty(optarg) && !valid_shell(optarg))
return r;
break;
- case ARG_NOSUID:
- case ARG_NODEV:
- case ARG_NOEXEC:
- case ARG_LOCKED:
- case ARG_KILL_PROCESSES:
- case ARG_ENFORCE_PASSWORD_POLICY:
- case ARG_AUTO_LOGIN:
- case ARG_PASSWORD_CHANGE_NOW: {
- const char *field =
- c == ARG_LOCKED ? "locked" :
- c == ARG_NOSUID ? "mountNoSuid" :
- c == ARG_NODEV ? "mountNoDevices" :
- c == ARG_NOEXEC ? "mountNoExecute" :
- c == ARG_KILL_PROCESSES ? "killProcesses" :
- c == ARG_ENFORCE_PASSWORD_POLICY ? "enforcePasswordPolicy" :
- c == ARG_AUTO_LOGIN ? "autoLogin" :
- c == ARG_PASSWORD_CHANGE_NOW ? "passwordChangeNow" :
- NULL;
- assert(field);
-
- r = parse_boolean_field(match_identity ?: &arg_identity_extra, field, optarg);
+ case ARG_DEFAULT_AREA:
+ r = parse_filename_field(match_identity ?: &arg_identity_extra, "defaultArea", optarg);
if (r < 0)
return r;
break;
- }
-
- case 'P':
- r = sd_json_variant_set_field_boolean(&arg_identity_extra, "enforcePasswordPolicy", false);
- if (r < 0)
- return log_error_errno(r, "Failed to set %s field: %m", "enforcePasswordPolicy");
- break;
- case ARG_DISK_SIZE:
- r = parse_disk_size_field(match_identity ?: &arg_identity_extra_this_machine, optarg);
+ case ARG_SSH_AUTHORIZED_KEYS:
+ r = parse_ssh_authorized_keys(&arg_identity_extra_privileged, "sshAuthorizedKeys", optarg);
if (r < 0)
return r;
- break;
- case ARG_ACCESS_MODE:
- r = parse_mode_field(&arg_identity_extra, "accessMode", optarg);
- if (r < 0)
- return r;
break;
- case ARG_LUKS_DISCARD:
- case ARG_LUKS_OFFLINE_DISCARD: {
- const char *field = c == ARG_LUKS_DISCARD ? "luksDiscard" : "luksOfflineDiscard";
-
- r = parse_boolean_field(match_identity ?: &arg_identity_extra, field, optarg);
- if (r < 0)
+ case ARG_PKCS11_TOKEN_URI:
+ r = parse_pkcs11_token_uri_field(optarg);
+ if (r <= 0)
return r;
break;
- }
-
- case ARG_LUKS_VOLUME_KEY_SIZE:
- case ARG_LUKS_PBKDF_FORCE_ITERATIONS:
- case ARG_LUKS_PBKDF_PARALLEL_THREADS:
- case ARG_RATE_LIMIT_BURST: {
- const char *field =
- c == ARG_LUKS_VOLUME_KEY_SIZE ? "luksVolumeKeySize" :
- c == ARG_LUKS_PBKDF_FORCE_ITERATIONS ? "luksPbkdfForceIterations" :
- c == ARG_LUKS_PBKDF_PARALLEL_THREADS ? "luksPbkdfParallelThreads" :
- c == ARG_RATE_LIMIT_BURST ? "rateLimitBurst" :
- NULL;
- assert(field);
- r = parse_unsigned_field(match_identity ?: &arg_identity_extra, field, optarg);
- if (r < 0)
+ case ARG_FIDO2_DEVICE:
+ r = parse_fido2_device_field(optarg);
+ if (r <= 0)
return r;
break;
- }
- case ARG_LUKS_SECTOR_SIZE:
- r = parse_sector_size_field(match_identity ?: &arg_identity_extra, "luksSectorSize", optarg);
+ case ARG_FIDO2_WITH_PIN:
+ r = parse_boolean_argument("--fido2-with-client-pin=", optarg, NULL);
if (r < 0)
return r;
+
+ SET_FLAG(arg_fido2_lock_with, FIDO2ENROLL_PIN, r);
break;
- case ARG_UMASK:
- r = parse_mode_field(match_identity ?: &arg_identity_extra, "umask", optarg);
+ case ARG_FIDO2_WITH_UP:
+ r = parse_boolean_argument("--fido2-with-user-presence=", optarg, NULL);
if (r < 0)
return r;
+
+ SET_FLAG(arg_fido2_lock_with, FIDO2ENROLL_UP, r);
break;
- case ARG_SSH_AUTHORIZED_KEYS:
- r = parse_ssh_authorized_keys(&arg_identity_extra_privileged, "sshAuthorizedKeys", optarg);
+ case ARG_FIDO2_WITH_UV:
+ r = parse_boolean_argument("--fido2-with-user-verification=", optarg, NULL);
if (r < 0)
return r;
+ SET_FLAG(arg_fido2_lock_with, FIDO2ENROLL_UV, r);
break;
- case ARG_NOT_BEFORE:
- case ARG_NOT_AFTER:
- case 'e': {
- const char *field = c == ARG_NOT_BEFORE ? "notBeforeUSec" : "notAfterUSec";
+ case ARG_RECOVERY_KEY:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --recovery-key= argument: %s", optarg);
+ arg_recovery_key = r;
- r = parse_timestamp_field(match_identity ?: &arg_identity_extra, field, optarg);
+ r = drop_from_identity("recoveryKey", "recoveryKeyType");
if (r < 0)
return r;
break;
- }
- case ARG_PASSWORD_CHANGE_MIN:
+ case 'b':
+ case ARG_AVATAR:
+ case ARG_LOGIN_BACKGROUND: {
+ _cleanup_close_ int fd = -EBADF;
+ _cleanup_free_ char *path = NULL, *filename = NULL;
+
+ if (c == 'b') {
+ char *eq;
+
+ if (isempty(optarg)) { /* --blob= deletes everything, including existing blob dirs */
+ hashmap_clear(arg_blob_files);
+ arg_blob_dir = mfree(arg_blob_dir);
+ arg_blob_clear = true;
+ break;
+ }
+
+ eq = strrchr(optarg, '=');
+ if (!eq) { /* --blob=/some/path replaces the blob dir */
+ r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_blob_dir);
+ if (r < 0)
+ return r;
+ break;
+ }
+
+ /* --blob=filename=/some/path replaces the file "filename" with /some/path */
+ filename = strndup(optarg, eq - optarg);
+ if (!filename)
+ return log_oom();
+
+ if (isempty(filename))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Can't parse blob file assignment: %s", optarg);
+ if (!suitable_blob_filename(filename))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid blob filename: %s", filename);
+
+ r = parse_path_argument(eq + 1, /* suppress_root= */ false, &path);
+ if (r < 0)
+ return r;
+ } else {
+ const char *well_known_filename =
+ c == ARG_AVATAR ? "avatar" :
+ c == ARG_LOGIN_BACKGROUND ? "login-background" :
+ NULL;
+ assert(well_known_filename);
+
+ filename = strdup(well_known_filename);
+ if (!filename)
+ return log_oom();
+
+ r = parse_path_argument(optarg, /* suppress_root= */ false, &path);
+ if (r < 0)
+ return r;
+ }
+
+ if (path) {
+ fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
+ if (fd < 0)
+ return log_error_errno(errno, "Failed to open %s: %m", path);
+
+ if (fd_verify_regular(fd) < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Provided blob is not a regular file: %s", path);
+ } else
+ fd = -EBADF; /* Delete the file */
+
+ r = hashmap_ensure_put(&arg_blob_files, &blob_fd_hash_ops, filename, FD_TO_PTR(fd));
+ if (r < 0)
+ return log_error_errno(r, "Failed to map %s to %s in blob directory: %m", path, filename);
+ TAKE_PTR(filename); /* hashmap takes ownership */
+ TAKE_FD(fd);
+
+ break;
+ }
+
+ case ARG_LOCKED:
+ r = parse_boolean_field(match_identity ?: &arg_identity_extra, "locked", optarg);
+ if (r < 0)
+ return r;
+ break;
+
+ case ARG_NOT_BEFORE:
+ case ARG_NOT_AFTER:
+ case 'e': {
+ const char *field = c == ARG_NOT_BEFORE ? "notBeforeUSec" : "notAfterUSec";
+
+ r = parse_timestamp_field(match_identity ?: &arg_identity_extra, field, optarg);
+ if (r < 0)
+ return r;
+ break;
+ }
+
+ case ARG_RATE_LIMIT_INTERVAL:
+ r = parse_time_field(match_identity ?: &arg_identity_extra, "rateLimitIntervalUSec", optarg);
+ if (r < 0)
+ return r;
+ break;
+
+ case ARG_RATE_LIMIT_BURST:
+ r = parse_unsigned_field(match_identity ?: &arg_identity_extra, "rateLimitBurst", optarg);
+ if (r < 0)
+ return r;
+ break;
+
+ case ARG_PASSWORD_HINT:
+ r = parse_string_field(&arg_identity_extra_privileged, "passwordHint", optarg);
+ if (r < 0)
+ return r;
+
+ string_erase(optarg);
+ break;
+
+ case ARG_ENFORCE_PASSWORD_POLICY:
+ r = parse_boolean_field(match_identity ?: &arg_identity_extra, "enforcePasswordPolicy", optarg);
+ if (r < 0)
+ return r;
+ break;
+
+ case 'P':
+ r = sd_json_variant_set_field_boolean(&arg_identity_extra, "enforcePasswordPolicy", false);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set %s field: %m", "enforcePasswordPolicy");
+ break;
+
+ case ARG_PASSWORD_CHANGE_NOW:
+ r = parse_boolean_field(match_identity ?: &arg_identity_extra, "passwordChangeNow", optarg);
+ if (r < 0)
+ return r;
+ break;
+
+ case ARG_PASSWORD_CHANGE_MIN:
case ARG_PASSWORD_CHANGE_MAX:
case ARG_PASSWORD_CHANGE_WARN:
case ARG_PASSWORD_CHANGE_INACTIVE: {
break;
}
- case ARG_STORAGE:
- case ARG_FS_TYPE:
- case ARG_LUKS_CIPHER:
- case ARG_LUKS_CIPHER_MODE:
- case ARG_LUKS_PBKDF_TYPE:
- case ARG_LUKS_PBKDF_HASH_ALGORITHM: {
- const char *field =
- c == ARG_STORAGE ? "storage" :
- c == ARG_FS_TYPE ? "fileSystemType" :
- c == ARG_LUKS_CIPHER ? "luksCipher" :
- c == ARG_LUKS_CIPHER_MODE ? "luksCipherMode" :
- c == ARG_LUKS_PBKDF_TYPE ? "luksPbkdfType" :
- c == ARG_LUKS_PBKDF_HASH_ALGORITHM ? "luksPbkdfHashAlgorithm" :
- NULL;
- assert(field);
-
- sd_json_variant **identity =
- match_identity ?:
- IN_SET(c, ARG_STORAGE, ARG_FS_TYPE) ?
- &arg_identity_extra_this_machine : &arg_identity_extra;
-
- if (!string_is_safe(optarg, STRING_ALLOW_GLOBS))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Parameter for field %s not valid: %s", field, optarg);
-
- r = parse_string_field(identity, field, optarg);
+ case ARG_DISK_SIZE:
+ r = parse_disk_size_field(match_identity ?: &arg_identity_extra_this_machine, optarg);
if (r < 0)
return r;
break;
- }
-
- case ARG_LUKS_PBKDF_TIME_COST:
- case ARG_RATE_LIMIT_INTERVAL:
- case ARG_STOP_DELAY: {
- const char *field =
- c == ARG_LUKS_PBKDF_TIME_COST ? "luksPbkdfTimeCostUSec" :
- c == ARG_RATE_LIMIT_INTERVAL ? "rateLimitIntervalUSec" :
- c == ARG_STOP_DELAY ? "stopDelayUSec" :
- NULL;
- assert(field);
- r = parse_time_field(match_identity ?: &arg_identity_extra, field, optarg);
+ case ARG_NICE:
+ r = parse_nice_field(match_identity ?: &arg_identity_extra, "niceLevel", optarg);
if (r < 0)
return r;
break;
- }
- case 'G':
- r = parse_group_field(match_identity ?: &arg_identity_extra, "memberOf", optarg);
+ case ARG_RLIMIT:
+ r = parse_rlimit_field(&arg_identity_extra_rlimits, "resourceLimits", optarg);
if (r < 0)
return r;
break;
return r;
break;
- case ARG_MEMORY_MAX:
case ARG_MEMORY_HIGH:
- case ARG_LUKS_PBKDF_MEMORY_COST: {
- const char *field =
- c == ARG_MEMORY_MAX ? "memoryMax" :
- c == ARG_MEMORY_HIGH ? "memoryHigh" :
- c == ARG_LUKS_PBKDF_MEMORY_COST ? "luksPbkdfMemoryCost" :
- NULL;
+ r = parse_size_field(match_identity ?: &arg_identity_extra_this_machine, "memoryHigh", optarg);
+ if (r < 0)
+ return r;
+ break;
- r = parse_size_field(match_identity ?: &arg_identity_extra_this_machine, field, optarg);
+ case ARG_MEMORY_MAX:
+ r = parse_size_field(match_identity ?: &arg_identity_extra_this_machine, "memoryMax", optarg);
if (r < 0)
return r;
break;
- }
case ARG_CPU_WEIGHT:
case ARG_IO_WEIGHT: {
break;
}
- case ARG_PKCS11_TOKEN_URI:
- r = parse_pkcs11_token_uri_field(optarg);
- if (r <= 0)
+ case ARG_TMP_LIMIT:
+ case ARG_DEV_SHM_LIMIT: {
+ const char *field =
+ c == ARG_TMP_LIMIT ? "tmpLimit" :
+ c == ARG_DEV_SHM_LIMIT ? "devShmLimit" :
+ NULL;
+ const char *field_scale =
+ c == ARG_TMP_LIMIT ? "tmpLimitScale" :
+ c == ARG_DEV_SHM_LIMIT ? "devShmLimitScale" :
+ NULL;
+
+ assert(field);
+ assert(field_scale);
+
+ r = parse_tmpfs_limit_field(match_identity ?: &arg_identity_extra,
+ field, field_scale, optarg);
+ if (r < 0)
return r;
break;
+ }
- case ARG_FIDO2_CRED_ALG:
- r = parse_fido2_algorithm(optarg, &arg_fido2_cred_alg);
+ case ARG_STORAGE: {
+ if (!string_is_safe(optarg, STRING_ALLOW_GLOBS))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Parameter for field %s not valid: %s", "storage", optarg);
+
+ r = parse_string_field(match_identity ?: &arg_identity_extra_this_machine, "storage", optarg);
if (r < 0)
- return log_error_errno(r, "Failed to parse COSE algorithm: %s", optarg);
+ return r;
break;
+ }
- case ARG_FIDO2_DEVICE:
- r = parse_fido2_device_field(optarg);
- if (r <= 0)
+ case ARG_IMAGE_PATH:
+ r = parse_path_field(match_identity ?: &arg_identity_extra_this_machine, "imagePath", optarg);
+ if (r < 0)
return r;
break;
- case ARG_FIDO2_WITH_PIN:
- r = parse_boolean_argument("--fido2-with-client-pin=", optarg, NULL);
+ case ARG_DROP_CACHES:
+ r = parse_boolean_field(match_identity ?: &arg_identity_extra, "dropCaches", optarg);
if (r < 0)
return r;
-
- SET_FLAG(arg_fido2_lock_with, FIDO2ENROLL_PIN, r);
break;
- case ARG_FIDO2_WITH_UP:
- r = parse_boolean_argument("--fido2-with-user-presence=", optarg, NULL);
+ case ARG_FS_TYPE: {
+ if (!string_is_safe(optarg, STRING_ALLOW_GLOBS))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Parameter for field %s not valid: %s", "fileSystemType", optarg);
+
+ r = parse_string_field(match_identity ?: &arg_identity_extra_this_machine, "fileSystemType", optarg);
if (r < 0)
return r;
-
- SET_FLAG(arg_fido2_lock_with, FIDO2ENROLL_UP, r);
break;
+ }
- case ARG_FIDO2_WITH_UV:
- r = parse_boolean_argument("--fido2-with-user-verification=", optarg, NULL);
+ case ARG_LUKS_DISCARD:
+ case ARG_LUKS_OFFLINE_DISCARD: {
+ const char *field = c == ARG_LUKS_DISCARD ? "luksDiscard" : "luksOfflineDiscard";
+
+ r = parse_boolean_field(match_identity ?: &arg_identity_extra, field, optarg);
if (r < 0)
return r;
-
- SET_FLAG(arg_fido2_lock_with, FIDO2ENROLL_UV, r);
break;
+ }
- case ARG_RECOVERY_KEY:
- r = parse_boolean(optarg);
- if (r < 0)
- return log_error_errno(r, "Failed to parse --recovery-key= argument: %s", optarg);
- arg_recovery_key = r;
+ case ARG_LUKS_CIPHER: {
+ if (!string_is_safe(optarg, STRING_ALLOW_GLOBS))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Parameter for field %s not valid: %s", "luksCipher", optarg);
- r = drop_from_identity("recoveryKey", "recoveryKeyType");
+ r = parse_string_field(match_identity ?: &arg_identity_extra, "luksCipher", optarg);
if (r < 0)
return r;
break;
+ }
- case ARG_AUTO_RESIZE_MODE:
- r = parse_auto_resize_mode_field(match_identity ?: &arg_identity_extra,
- "autoResizeMode", optarg);
+ case ARG_LUKS_CIPHER_MODE: {
+ if (!string_is_safe(optarg, STRING_ALLOW_GLOBS))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Parameter for field %s not valid: %s", "luksCipherMode", optarg);
+
+ r = parse_string_field(match_identity ?: &arg_identity_extra, "luksCipherMode", optarg);
if (r < 0)
return r;
break;
+ }
- case ARG_REBALANCE_WEIGHT:
- r = parse_rebalance_weight(match_identity ?: &arg_identity_extra,
- "rebalanceWeight", optarg);
+ case ARG_LUKS_VOLUME_KEY_SIZE:
+ r = parse_unsigned_field(match_identity ?: &arg_identity_extra, "luksVolumeKeySize", optarg);
if (r < 0)
return r;
break;
- case 'j':
- arg_json_format_flags = SD_JSON_FORMAT_PRETTY_AUTO|SD_JSON_FORMAT_COLOR_AUTO;
- break;
+ case ARG_LUKS_PBKDF_TYPE: {
+ if (!string_is_safe(optarg, STRING_ALLOW_GLOBS))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Parameter for field %s not valid: %s", "luksPbkdfType", optarg);
- case ARG_JSON:
- r = parse_json_argument(optarg, &arg_json_format_flags);
- if (r <= 0)
+ r = parse_string_field(match_identity ?: &arg_identity_extra, "luksPbkdfType", optarg);
+ if (r < 0)
return r;
-
break;
+ }
- case 'E':
- if (arg_export_format == EXPORT_FORMAT_FULL)
- arg_export_format = EXPORT_FORMAT_STRIPPED;
- else if (arg_export_format == EXPORT_FORMAT_STRIPPED)
- arg_export_format = EXPORT_FORMAT_MINIMAL;
- else
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specifying -E more than twice is not supported.");
+ case ARG_LUKS_PBKDF_HASH_ALGORITHM: {
+ if (!string_is_safe(optarg, STRING_ALLOW_GLOBS))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Parameter for field %s not valid: %s", "luksPbkdfHashAlgorithm", optarg);
- arg_json_format_flags &= ~SD_JSON_FORMAT_OFF;
- if (arg_json_format_flags == 0)
- arg_json_format_flags = SD_JSON_FORMAT_PRETTY_AUTO|SD_JSON_FORMAT_COLOR_AUTO;
+ r = parse_string_field(match_identity ?: &arg_identity_extra, "luksPbkdfHashAlgorithm", optarg);
+ if (r < 0)
+ return r;
break;
+ }
- case ARG_EXPORT_FORMAT:
- if (streq(optarg, "help"))
- return DUMP_STRING_TABLE(export_format, ExportFormat, _EXPORT_FORMAT_MAX);
-
- arg_export_format = export_format_from_string(optarg);
- if (arg_export_format < 0)
- return log_error_errno(arg_export_format, "Invalid export format: %s", optarg);
-
+ case ARG_LUKS_PBKDF_TIME_COST:
+ r = parse_time_field(match_identity ?: &arg_identity_extra, "luksPbkdfTimeCostUSec", optarg);
+ if (r < 0)
+ return r;
break;
- case ARG_DROP_CACHES:
- r = parse_boolean_field(match_identity ?: &arg_identity_extra, "dropCaches", optarg);
+ case ARG_LUKS_PBKDF_MEMORY_COST:
+ r = parse_size_field(match_identity ?: &arg_identity_extra_this_machine, "luksPbkdfMemoryCost", optarg);
if (r < 0)
return r;
break;
- case ARG_CAPABILITY_AMBIENT_SET:
- r = parse_capability_set_field(match_identity ?: &arg_identity_extra,
- &arg_capability_ambient_set,
- "capabilityAmbientSet", optarg);
+ case ARG_LUKS_PBKDF_PARALLEL_THREADS:
+ r = parse_unsigned_field(match_identity ?: &arg_identity_extra, "luksPbkdfParallelThreads", optarg);
if (r < 0)
return r;
break;
- case ARG_CAPABILITY_BOUNDING_SET:
- r = parse_capability_set_field(match_identity ?: &arg_identity_extra,
- &arg_capability_bounding_set,
- "capabilityBoundingSet", optarg);
+ case ARG_LUKS_SECTOR_SIZE:
+ r = parse_sector_size_field(match_identity ?: &arg_identity_extra, "luksSectorSize", optarg);
if (r < 0)
return r;
break;
- case ARG_PROMPT_NEW_USER:
- arg_prompt_new_user = true;
+ case ARG_LUKS_EXTRA_MOUNT_OPTIONS:
+ r = parse_string_field(match_identity ?: &arg_identity_extra, "luksExtraMountOptions", optarg);
+ if (r < 0)
+ return r;
break;
- case 'b':
- case ARG_AVATAR:
- case ARG_LOGIN_BACKGROUND: {
- _cleanup_close_ int fd = -EBADF;
- _cleanup_free_ char *path = NULL, *filename = NULL;
+ case ARG_LUKS_PBKDF_FORCE_ITERATIONS:
+ r = parse_unsigned_field(match_identity ?: &arg_identity_extra, "luksPbkdfForceIterations", optarg);
+ if (r < 0)
+ return r;
+ break;
- if (c == 'b') {
- char *eq;
+ case ARG_AUTO_RESIZE_MODE:
+ r = parse_auto_resize_mode_field(match_identity ?: &arg_identity_extra,
+ "autoResizeMode", optarg);
+ if (r < 0)
+ return r;
+ break;
- if (isempty(optarg)) { /* --blob= deletes everything, including existing blob dirs */
- hashmap_clear(arg_blob_files);
- arg_blob_dir = mfree(arg_blob_dir);
- arg_blob_clear = true;
- break;
- }
+ case ARG_REBALANCE_WEIGHT:
+ r = parse_rebalance_weight(match_identity ?: &arg_identity_extra,
+ "rebalanceWeight", optarg);
+ if (r < 0)
+ return r;
+ break;
- eq = strrchr(optarg, '=');
- if (!eq) { /* --blob=/some/path replaces the blob dir */
- r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_blob_dir);
- if (r < 0)
- return r;
- break;
- }
+ case ARG_NOSUID:
+ r = parse_boolean_field(match_identity ?: &arg_identity_extra, "mountNoSuid", optarg);
+ if (r < 0)
+ return r;
+ break;
- /* --blob=filename=/some/path replaces the file "filename" with /some/path */
- filename = strndup(optarg, eq - optarg);
- if (!filename)
- return log_oom();
+ case ARG_NODEV:
+ r = parse_boolean_field(match_identity ?: &arg_identity_extra, "mountNoDevices", optarg);
+ if (r < 0)
+ return r;
+ break;
- if (isempty(filename))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Can't parse blob file assignment: %s", optarg);
- if (!suitable_blob_filename(filename))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid blob filename: %s", filename);
+ case ARG_NOEXEC:
+ r = parse_boolean_field(match_identity ?: &arg_identity_extra, "mountNoExecute", optarg);
+ if (r < 0)
+ return r;
+ break;
- r = parse_path_argument(eq + 1, /* suppress_root= */ false, &path);
- if (r < 0)
- return r;
- } else {
- const char *well_known_filename =
- c == ARG_AVATAR ? "avatar" :
- c == ARG_LOGIN_BACKGROUND ? "login-background" :
- NULL;
- assert(well_known_filename);
+ case ARG_CIFS_DOMAIN:
+ r = parse_string_field(match_identity ?: &arg_identity_extra, "cifsDomain", optarg);
+ if (r < 0)
+ return r;
+ break;
- filename = strdup(well_known_filename);
- if (!filename)
- return log_oom();
+ case ARG_CIFS_USER_NAME:
+ r = parse_string_field(match_identity ?: &arg_identity_extra, "cifsUserName", optarg);
+ if (r < 0)
+ return r;
+ break;
- r = parse_path_argument(optarg, /* suppress_root= */ false, &path);
+ case ARG_CIFS_SERVICE:
+ if (!isempty(optarg)) {
+ r = parse_cifs_service(optarg, /* ret_host= */ NULL, /* ret_service= */ NULL, /* ret_path= */ NULL);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to validate CIFS service name: %s", optarg);
}
- if (path) {
- fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return log_error_errno(errno, "Failed to open %s: %m", path);
-
- if (fd_verify_regular(fd) < 0)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Provided blob is not a regular file: %s", path);
- } else
- fd = -EBADF; /* Delete the file */
-
- r = hashmap_ensure_put(&arg_blob_files, &blob_fd_hash_ops, filename, FD_TO_PTR(fd));
+ r = parse_string_field(match_identity ?: &arg_identity_extra, "cifsService", optarg);
if (r < 0)
- return log_error_errno(r, "Failed to map %s to %s in blob directory: %m", path, filename);
- TAKE_PTR(filename); /* hashmap takes ownership */
- TAKE_FD(fd);
-
+ return r;
break;
- }
-
- case ARG_TMP_LIMIT:
- case ARG_DEV_SHM_LIMIT: {
- const char *field =
- c == ARG_TMP_LIMIT ? "tmpLimit" :
- c == ARG_DEV_SHM_LIMIT ? "devShmLimit" :
- NULL;
- const char *field_scale =
- c == ARG_TMP_LIMIT ? "tmpLimitScale" :
- c == ARG_DEV_SHM_LIMIT ? "devShmLimitScale" :
- NULL;
- assert(field);
- assert(field_scale);
+ case ARG_CIFS_EXTRA_MOUNT_OPTIONS:
+ r = parse_string_field(match_identity ?: &arg_identity_extra, "cifsExtraMountOptions", optarg);
+ if (r < 0)
+ return r;
+ break;
- r = parse_tmpfs_limit_field(match_identity ?: &arg_identity_extra,
- field, field_scale, optarg);
+ case ARG_STOP_DELAY:
+ r = parse_time_field(match_identity ?: &arg_identity_extra, "stopDelayUSec", optarg);
if (r < 0)
return r;
break;
- }
- case ARG_DEFAULT_AREA:
- r = parse_filename_field(match_identity ?: &arg_identity_extra, "defaultArea", optarg);
+ case ARG_KILL_PROCESSES:
+ r = parse_boolean_field(match_identity ?: &arg_identity_extra, "killProcesses", optarg);
if (r < 0)
return r;
break;
- case ARG_KEY_NAME:
- if (!isempty(optarg) && !filename_is_valid(optarg))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Parameter for --key-name= not a valid filename: %s", optarg);
+ case ARG_AUTO_LOGIN:
+ r = parse_boolean_field(match_identity ?: &arg_identity_extra, "autoLogin", optarg);
+ if (r < 0)
+ return r;
+ break;
- r = free_and_strdup_warn(&arg_key_name, empty_to_null(optarg));
+ case ARG_SESSION_LAUNCHER:
+ r = parse_string_field(match_identity ?: &arg_identity_extra, "preferredSessionLauncher", optarg);
if (r < 0)
return r;
break;
- case ARG_SEIZE:
- r = parse_boolean_argument("--seize=", optarg, &arg_seize);
+ case ARG_SESSION_TYPE:
+ r = parse_string_field(match_identity ?: &arg_identity_extra, "preferredSessionType", optarg);
if (r < 0)
return r;
break;
+ case ARG_FIDO2_CRED_ALG:
+ r = parse_fido2_algorithm(optarg, &arg_fido2_cred_alg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse COSE algorithm: %s", optarg);
+ break;
+
case ARG_MATCH:
if (streq(optarg, "any"))
match_identity = &arg_identity_extra;
match_identity = &arg_identity_extra_other_machines;
break;
- case ARG_PROMPT_SHELL:
- r = parse_boolean_argument("--prompt-shell=", optarg, &arg_prompt_shell);
- if (r < 0)
- return r;
-
- break;
-
- case ARG_PROMPT_GROUPS:
- r = parse_boolean_argument("--prompt-groups=", optarg, &arg_prompt_groups);
- if (r < 0)
- return r;
-
- break;
-
- case ARG_CHROME:
- r = parse_boolean_argument("--chrome=", optarg, &arg_chrome);
- if (r < 0)
- return r;
-
- break;
-
- case ARG_MUTE_CONSOLE:
- r = parse_boolean_argument("--mute-console=", optarg, &arg_mute_console);
- if (r < 0)
- return r;
-
- break;
-
case '?':
return -EINVAL;