Hello community,

here is the log from the commit of package yast2-users for openSUSE:Factory 
checked in at 2016-09-27 13:43:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yast2-users (Old)
 and      /work/SRC/openSUSE:Factory/.yast2-users.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "yast2-users"

Changes:
--------
--- /work/SRC/openSUSE:Factory/yast2-users/yast2-users.changes  2016-09-08 
17:38:06.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.yast2-users.new/yast2-users.changes     
2016-09-27 13:43:10.000000000 +0200
@@ -1,0 +2,21 @@
+Wed Sep 21 13:25:22 UTC 2016 - [email protected]
+
+- Do not require yast2-ldap for build time tests (bsc#999203).
+- 3.1.60
+
+-------------------------------------------------------------------
+Tue Sep 20 15:10:23 UTC 2016 - [email protected]
+
+- Prevent a potential security issue if the target authorized_keys
+  file is not a regular file (related to FATE#319471)
+- Fix authorized_keys section of AutoYaST schema
+- 3.1.59
+
+-------------------------------------------------------------------
+Fri Sep 16 09:03:32 UTC 2016 - [email protected]
+
+- Add support to specify SSH authorized keys in the profile
+  (FATE#319471)
+- 3.1.58
+
+-------------------------------------------------------------------

Old:
----
  yast2-users-3.1.57.tar.bz2

New:
----
  yast2-users-3.1.60.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ yast2-users.spec ++++++
--- /var/tmp/diff_new_pack.FBazxm/_old  2016-09-27 13:43:11.000000000 +0200
+++ /var/tmp/diff_new_pack.FBazxm/_new  2016-09-27 13:43:11.000000000 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-users
-Version:        3.1.57
+Version:        3.1.60
 Release:        0
 
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
@@ -33,7 +33,6 @@
 BuildRequires:  yast2
 BuildRequires:  yast2-core-devel
 BuildRequires:  yast2-devtools >= 3.1.10
-BuildRequires:  yast2-ldap >= 3.1.2
 BuildRequires:  yast2-perl-bindings
 BuildRequires:  yast2-security
 BuildRequires:  yast2-testsuite
@@ -46,19 +45,7 @@
 Requires:       yast2-country
 Requires:       yast2-pam
 Requires:       yast2-security
-Obsoletes:      y2c_users
-Obsoletes:      y2t_inst-user
-Obsoletes:      y2t_users
-Obsoletes:      yast2-config-users
-Obsoletes:      yast2-trans-inst-user
-Obsoletes:      yast2-trans-users
 Obsoletes:      yast2-users-devel-doc
-Provides:       y2c_users
-Provides:       y2t_inst-user
-Provides:       y2t_users
-Provides:       yast2-config-users
-Provides:       yast2-trans-inst-user
-Provides:       yast2-trans-users
 Conflicts:      autoyast2 < 3.1.92
 # older storage uses removed deprecated method, see 
https://github.com/yast/yast-storage/pull/187
 Conflicts:      yast2-storage < 3.1.75
@@ -90,6 +77,8 @@
 %yast_build
 
 %install
+# make testsuite/modules/Ldap.rb visible
+export Y2BASE_Y2DIR=`pwd`/testsuite
 %yast_install
 
 %files
@@ -103,6 +92,7 @@
 %{yast_libdir}/users/clients/*
 %{yast_desktopdir}/*.desktop
 %{yast_moduledir}/*.pm
+%{yast_moduledir}/SSHAuthorizedKeys.rb
 %{yast_moduledir}/UsersUI.rb
 %{yast_moduledir}/YaPI/*.pm
 %{yast_yncludedir}/users/*

++++++ yast2-users-3.1.57.tar.bz2 -> yast2-users-3.1.60.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/.travis.yml 
new/yast2-users-3.1.60/.travis.yml
--- old/yast2-users-3.1.57/.travis.yml  2016-09-02 16:36:17.000000000 +0200
+++ new/yast2-users-3.1.60/.travis.yml  2016-09-21 16:21:01.000000000 +0200
@@ -5,12 +5,11 @@
     # disable rvm, use system Ruby
     - rvm reset
     - wget 
https://raw.githubusercontent.com/yast/yast-devtools/master/travis-tools/travis_setup.sh
-    - sh ./travis_setup.sh -p "rake yast2-devtools yast2-testsuite yast2 
yast2-perl-bindings yast2-core-dev yast2-ldap yast2-perl-bindings 
yast2-security libcrack2-dev doxygen libdigest-sha1-perl" -g "rspec:3.3.0 
yast-rake gettext"
+    - sh ./travis_setup.sh -p "rake yast2-devtools yast2-testsuite yast2 
yast2-perl-bindings yast2-core-dev yast2-perl-bindings yast2-security 
libcrack2-dev doxygen libdigest-sha1-perl" -g "rspec:3.3.0 yast-rake gettext"
 script:
     - rake check:syntax
     - rake check:pot
     - make -f Makefile.cvs
     - make
     - sudo make install
-    - make check
-
+    - Y2BASE_Y2DIR=$(pwd)/testsuite make check
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/package/yast2-users.changes 
new/yast2-users-3.1.60/package/yast2-users.changes
--- old/yast2-users-3.1.57/package/yast2-users.changes  2016-09-02 
16:36:17.000000000 +0200
+++ new/yast2-users-3.1.60/package/yast2-users.changes  2016-09-21 
16:21:01.000000000 +0200
@@ -1,4 +1,25 @@
 -------------------------------------------------------------------
+Wed Sep 21 13:25:22 UTC 2016 - [email protected]
+
+- Do not require yast2-ldap for build time tests (bsc#999203).
+- 3.1.60
+
+-------------------------------------------------------------------
+Tue Sep 20 15:10:23 UTC 2016 - [email protected]
+
+- Prevent a potential security issue if the target authorized_keys
+  file is not a regular file (related to FATE#319471)
+- Fix authorized_keys section of AutoYaST schema
+- 3.1.59
+
+-------------------------------------------------------------------
+Fri Sep 16 09:03:32 UTC 2016 - [email protected]
+
+- Add support to specify SSH authorized keys in the profile
+  (FATE#319471)
+- 3.1.58
+
+-------------------------------------------------------------------
 Fri Sep  2 15:16:37 CEST 2016 - [email protected]
 
 - AutoYaST: Ignore Users without UID while checking for duplicate
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/package/yast2-users.spec 
new/yast2-users-3.1.60/package/yast2-users.spec
--- old/yast2-users-3.1.57/package/yast2-users.spec     2016-09-02 
16:36:17.000000000 +0200
+++ new/yast2-users-3.1.60/package/yast2-users.spec     2016-09-21 
16:21:01.000000000 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-users
-Version:        3.1.57
+Version:        3.1.60
 Release:        0
 
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
@@ -33,7 +33,6 @@
 BuildRequires:  yast2
 BuildRequires:  yast2-core-devel
 BuildRequires:  yast2-devtools >= 3.1.10
-BuildRequires:  yast2-ldap >= 3.1.2
 BuildRequires:  yast2-perl-bindings
 BuildRequires:  yast2-security
 BuildRequires:  yast2-testsuite
@@ -46,19 +45,7 @@
 Requires:       yast2-country
 Requires:       yast2-pam
 Requires:       yast2-security
-Obsoletes:      y2c_users
-Obsoletes:      y2t_inst-user
-Obsoletes:      y2t_users
-Obsoletes:      yast2-config-users
-Obsoletes:      yast2-trans-inst-user
-Obsoletes:      yast2-trans-users
 Obsoletes:      yast2-users-devel-doc
-Provides:       y2c_users
-Provides:       y2t_inst-user
-Provides:       y2t_users
-Provides:       yast2-config-users
-Provides:       yast2-trans-inst-user
-Provides:       yast2-trans-users
 Conflicts:      autoyast2 < 3.1.92
 # older storage uses removed deprecated method, see 
https://github.com/yast/yast-storage/pull/187
 Conflicts:      yast2-storage < 3.1.75
@@ -90,6 +77,8 @@
 %yast_build
 
 %install
+# make testsuite/modules/Ldap.rb visible
+export Y2BASE_Y2DIR=`pwd`/testsuite
 %yast_install
 
 %files
@@ -103,6 +92,7 @@
 %{yast_libdir}/users/clients/*
 %{yast_desktopdir}/*.desktop
 %{yast_moduledir}/*.pm
+%{yast_moduledir}/SSHAuthorizedKeys.rb
 %{yast_moduledir}/UsersUI.rb
 %{yast_moduledir}/YaPI/*.pm
 %{yast_yncludedir}/users/*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/src/Makefile.am 
new/yast2-users-3.1.60/src/Makefile.am
--- old/yast2-users-3.1.57/src/Makefile.am      2016-09-02 16:36:17.000000000 
+0200
+++ new/yast2-users-3.1.60/src/Makefile.am      2016-09-21 16:21:01.000000000 
+0200
@@ -1,6 +1,7 @@
 # Sources for users
 
 module_DATA = \
+  modules/SSHAuthorizedKeys.rb \
   modules/UsersUI.rb \
   modules/UsersRoutines.pm \
   modules/UsersPluginQuota.pm \
@@ -64,6 +65,8 @@
   lib/users/encryption_method.rb \
   lib/users/proposal.rb \
   lib/users/encryption_proposal.rb \
+  lib/users/ssh_authorized_keys_file.rb \
+  lib/users/ssh_authorized_keyring.rb \
   lib/users/users_database.rb
 
 scrconf_DATA = \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/src/autoyast-rnc/users.rnc 
new/yast2-users-3.1.60/src/autoyast-rnc/users.rnc
--- old/yast2-users-3.1.57/src/autoyast-rnc/users.rnc   2016-09-02 
16:36:17.000000000 +0200
+++ new/yast2-users-3.1.60/src/autoyast-rnc/users.rnc   2016-09-21 
16:21:01.000000000 +0200
@@ -34,6 +34,17 @@
     skel? &
     umask?
   }
+
+# by default, AutoYaST exports list entries as 'listentry'
+authorized_key =
+  element authorized_key { text } | element listentry { text }
+
+authorized_keys =
+  element authorized_keys {
+    LIST,
+    authorized_key*
+}
+
 expire = element expire { text }
 ud_group = element group { text }
 ud_groups = element groups { text }
@@ -55,7 +66,8 @@
     username? &
     u_group? &
     u_groups? &
-    password_settings?
+    password_settings? &
+    authorized_keys?
 }
 encrypted = element encrypted { BOOLEAN }
 fullname = element fullname { text }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-users-3.1.57/src/lib/users/ssh_authorized_keyring.rb 
new/yast2-users-3.1.60/src/lib/users/ssh_authorized_keyring.rb
--- old/yast2-users-3.1.57/src/lib/users/ssh_authorized_keyring.rb      
1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-users-3.1.60/src/lib/users/ssh_authorized_keyring.rb      
2016-09-21 16:21:01.000000000 +0200
@@ -0,0 +1,224 @@
+# Copyright (c) 2016 SUSE LLC.
+#  All Rights Reserved.
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of version 2 or 3 of the GNU General
+#  Public License as published by the Free Software Foundation.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, contact SUSE LLC.
+#
+#  To contact SUSE about this file by physical or electronic mail,
+#  you may find current contact information at www.suse.com
+
+require "yast"
+require "users/ssh_authorized_keys_file"
+
+module Yast
+  module Users
+    # Read, write and store SSH authorized keys.
+    #
+    # This class manages authorized keys for each home directory in the
+    # system.
+    class SSHAuthorizedKeyring
+      include Logger
+
+      # @return [Hash<String,Array<SSHAuthorizedKey>>] Authorized keys indexed 
by home directory
+      attr_reader :keys
+      private :keys
+
+      # Base class to use in file/directory problems
+      class PathError < StandardError
+        # @return [String] Path
+        attr_reader :path
+
+        # Constructor
+        #
+        # @param path [String] Path
+        def initialize(path)
+          @path = path
+          super(default_message)
+        end
+
+        # @return [String] Error message
+        def message
+          "#{super}: #{path}"
+        end
+
+        # Returns the default message to be used
+        #
+        # Derived clases should implement it.
+        #
+        # @return [String] Default message
+        def default_message
+          "Path error"
+        end
+      end
+
+      # The home directory does not exist.
+      class HomeDoesNotExist < PathError
+        # @return default_message [String] Default error message
+        def default_message; "Home directory does not exist" end
+      end
+
+      # The user's SSH configuration directory could not be created.
+      class CouldNotCreateSSHDirectory < PathError
+        # @return default_message [String] Default error message
+        def default_message; "SSH directory could not be created" end
+      end
+
+      # The user's SSH configuration directory is a link (potentially 
insecure).
+      class NotRegularSSHDirectory < PathError
+        # @return default_message [String] Default error message
+        def default_message; "SSH directory is not a regular directory" end
+      end
+
+      class NotRegularAuthorizedKeysFile < PathError
+        # @return default_message [String] Default error message
+        def default_message; "authorized_keys is not a regular file" end
+      end
+
+      # Constructor
+      def initialize
+        @keys = {}
+      end
+
+      # Add/register a keys
+      #
+      # This method does not make any change to the system. For that,
+      # see #write_keys.
+      #
+      # @param home [String] Home directory where the key will be stored
+      # @return [Array<SSHAuthorizedKey>] Registered authorized keys
+      def add_keys(home, new_keys)
+        keys[home] = new_keys
+      end
+
+      # Returns the keys for a given home directory
+      #
+      # @return [Array<SSHAuthorizedKey>] List of authorized keys
+      def [](home)
+        keys[home] || []
+      end
+
+      # Determines if the keyring is empty
+      #
+      # @return [Boolean] +true+ if it's empty; +false+ otherwise
+      def empty?
+        keys.empty?
+      end
+
+      # Read keys from a given home directory and add them to the keyring
+      #
+      # @param path [String] User's home directory
+      # @return [Boolean] +true+ if some key was found
+      def read_keys(home)
+        path = authorized_keys_path(home)
+        return false unless FileUtils::Exists(path)
+        authorized_keys = SSHAuthorizedKeysFile.new(path).keys
+        keys[home] = authorized_keys unless authorized_keys.empty?
+        log.info "Read #{authorized_keys.size} keys from #{path}"
+        !authorized_keys.empty?
+      end
+
+      # Write user keys to the given file
+      #
+      # If SSH_DIR does not exist in the given directory, it will be
+      # created inheriting owner/group and setting permissions to SSH_DIR_PERM.
+      #
+      # @param path [String] User's home directory
+      # @return [Boolean] +true+ if keys were written; +false+ otherwise
+      def write_keys(home)
+        return false if keys[home].nil?
+        if !FileUtils::Exists(home)
+          log.error("Home directory '#{home}' does not exist!")
+          raise HomeDoesNotExist.new(home)
+        end
+        user = FileUtils::GetOwnerUserID(home)
+        group = FileUtils::GetOwnerGroupID(home)
+        create_ssh_dir(home, user, group)
+        write_file(home, user, group)
+      end
+
+      private
+
+      # @return [String] Relative path to the SSH directory inside users' home
+      SSH_DIR = ".ssh".freeze
+      # @return [String] Authorized keys file name
+      AUTHORIZED_KEYS_FILE = "authorized_keys".freeze
+      # @return [String] Permissions to be set on SSH_DIR directory
+      SSH_DIR_PERMS = "0700".freeze
+      # @return [String] Permissions to be set on `authorized_keys` file
+      AUTHORIZED_KEYS_PERMS = "0600".freeze
+
+      # Determine the path to the user's SSH directory
+      #
+      # @param home [String] Home directory
+      # @return [String] Path to the user's SSH directory
+      #
+      # @see SSH_DIR
+      def ssh_dir_path(home)
+        File.join(home, SSH_DIR)
+      end
+
+      # Determine the path to the user's authorized keys file
+      #
+      # @param home [String] Home directory
+      # @return [String] Path to authorized keys file
+      #
+      # @see SSH_DIR
+      # @see AUTHORIZED_KEYS_FILE
+      #
+      # @see #ssh_dir_path
+      def authorized_keys_path(home)
+        File.join(ssh_dir_path(home), AUTHORIZED_KEYS_FILE)
+      end
+
+      # Find or creates the SSH directory
+      #
+      # This method sets up the SSH directory (usually .ssh). Although only 1
+      # level is needed (as SSH directory lives under $HOME/.ssh), this code
+      # should support changing SSH_DIR to something like `.config/ssh`.
+      #
+      # @param home  [String] Home directory where SSH directory must be 
created
+      # @param user  [Fixnum] Users's UID
+      # @param group [Fixnum] Group's GID
+      # @return [String] Returns the path to the first created directory
+      #
+      # @raise NotRegularSSHDirectory
+      # @raise CouldNotCreateSSHDirectory
+      def create_ssh_dir(home, user, group)
+        ssh_dir = ssh_dir_path(home)
+        if FileUtils::Exists(ssh_dir)
+          raise NotRegularSSHDirectory.new(ssh_dir) unless 
FileUtils::IsDirectory(ssh_dir)
+          return ssh_dir
+        end
+        ret = SCR.Execute(Path.new(".target.mkdir"), ssh_dir)
+        log.info("Creating SSH directory: #{ret}")
+        raise CouldNotCreateSSHDirectory.new(ssh_dir) unless ret
+        FileUtils::Chown("#{user}:#{group}", ssh_dir, false) && 
FileUtils::Chmod(SSH_DIR_PERMS, ssh_dir, false)
+      end
+
+      # Write authorized keys file
+      #
+      # @param path  [String] Path to file/directory
+      # @param user  [Fixnum] Users's UID
+      # @param group [Fixnum] Group's GID
+      # @param perms [String] Permissions (in form "0700")
+      def write_file(home, owner, group)
+        path = authorized_keys_path(home)
+        file = SSHAuthorizedKeysFile.new(path)
+        file.keys = keys[home]
+        log.info "Writing #{keys[home].size} keys in #{path}"
+        file.save && FileUtils::Chown("#{owner}:#{group}", path, false)
+      rescue SSHAuthorizedKeysFile::NotRegularFile
+        raise NotRegularAuthorizedKeysFile.new(path)
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-users-3.1.57/src/lib/users/ssh_authorized_keys_file.rb 
new/yast2-users-3.1.60/src/lib/users/ssh_authorized_keys_file.rb
--- old/yast2-users-3.1.57/src/lib/users/ssh_authorized_keys_file.rb    
1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-users-3.1.60/src/lib/users/ssh_authorized_keys_file.rb    
2016-09-21 16:21:01.000000000 +0200
@@ -0,0 +1,123 @@
+# Copyright (c) 2016 SUSE LLC.
+#  All Rights Reserved.
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of version 2 or 3 of the GNU General
+#  Public License as published by the Free Software Foundation.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, contact SUSE LLC.
+#
+#  To contact SUSE about this file by physical or electronic mail,
+#  you may find current contact information at www.suse.com
+
+Yast.import "FileUtils"
+
+module Yast
+  module Users
+    # Represents a `authorized_keys` SSH file.
+    #
+    # @example Adding a key to a file
+    #   path = "/home/user/.ssh/authorized_keys"
+    #   file = SSHAuthorizedKeysFile.new(path) #=> #<SSHAuthorizedKeysFile:...>
+    #   file.add_key("ssh-rsa 123ABC") #=> true
+    #   file.save #=> true
+    #
+    # @example Creating a new authorized_keys file
+    #   path = "/home/user/.ssh/authorized_keys2"
+    #   file = SSHAuthorizedKeysFile.new(path) #=> #<SSHAuthorizedKeysFile:...>
+    #   file.keys = ["ssh-rsa 123ABC"] #=> true
+    #   file.save #=> true
+    #
+    # @see man sshd(8)
+    class SSHAuthorizedKeysFile
+      include Logger
+
+      # @return [Pathname,String] Path to the file
+      attr_reader :path
+
+      # authorized_keys exists but it's not a regular file
+      class NotRegularFile < StandardError; end
+
+      # Constructor
+      #
+      # @param path [Pathname,String] Path to the file
+      def initialize(path)
+        @path = path.to_s
+      end
+
+      # Return the authorized keys present in the file
+      #
+      # @return [Array<String>] Array of keys
+      def keys
+        return @keys if @keys
+        content = SCR.Read(Path.new(".target.string"), path)
+        self.keys = content.nil? ? [] : content.split("\n")
+        @keys
+      end
+
+      # 
https://github.com/jordansissel/ruby-sshkeyauth/commit/12c9bb34399babf4040337e5695f3f453cd6745e#diff-4d8f3d488c1e25a30942c0e90f4e6ce4R14
+      AUTHORIZED_KEYS_REGEX =
+        /\A((?:[A-Za-z0-9-]+(?:="[^"]+")?,?)+)? *((?:ssh|ecdsa)-[^ ]+) *([^ 
]+) *(.+)?\z/
+
+      # Validate and add a key to the keyring
+      #
+      # The key is validated before adding it to the keyring.
+      #
+      # @param key [String] String that represents the key
+      # @return [Boolean] +true+ if the key was added; +false+ otherwise
+      def add_key(key)
+        new_key = key.strip
+        if valid_key?(new_key)
+          self.keys << new_key
+          true
+        else
+          log.warn("The key '#{key}' does not look like a valid SSH key")
+          false
+        end
+      end
+
+      # Set the authorized keys in the file
+      #
+      # It won't write the new keys to the file. For that, check the #save
+      # method.
+      #
+      # @param new_keys [Array<String>] SSH authorized keys
+      # @return [Array<String>] SSH authorized keys
+      #
+      # @see #save
+      # @see #keys
+      def keys=(new_keys)
+        @keys = []
+        new_keys.each { |k| add_key(k) }
+        keys
+      end
+
+      # Determines is a string qualifies like a valid keys
+      #
+      # @param key [String] SSH authorized keys
+      # @return [Boolean] +true+ if it's valid; +false+ otherwise
+      def valid_key?(key)
+        AUTHORIZED_KEYS_REGEX.match(key)
+      end
+
+      # Write keys to the file
+      #
+      # @return [Boolean] +true+ if file was written; +false+ otherwise.
+      def save
+        if FileUtils::Exists(path)
+          raise NotRegularFile unless FileUtils::IsFile(path)
+        else
+          SCR.Execute(Path.new(".target.bash"), "umask 0077 && touch #{path}")
+        end
+        content = keys.join("\n") + "\n"
+        SCR.Write(Path.new(".target.string"), path, content)
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/src/modules/SSHAuthorizedKeys.rb 
new/yast2-users-3.1.60/src/modules/SSHAuthorizedKeys.rb
--- old/yast2-users-3.1.57/src/modules/SSHAuthorizedKeys.rb     1970-01-01 
01:00:00.000000000 +0100
+++ new/yast2-users-3.1.60/src/modules/SSHAuthorizedKeys.rb     2016-09-21 
16:21:01.000000000 +0200
@@ -0,0 +1,113 @@
+# Copyright (c) 2016 SUSE LLC.
+#  All Rights Reserved.
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of version 2 or 3 of the GNU General
+#  Public License as published by the Free Software Foundation.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, contact SUSE LLC.
+#
+#  To contact SUSE about this file by physical or electronic mail,
+#  you may find current contact information at www.suse.com
+
+require "yast"
+require "users/ssh_authorized_keyring"
+
+Yast.import "Message"
+
+module Yast
+  # This module add support to handle SSH authorized keys.
+  #
+  # It's inteded to be a thin layer on top of SSHAuthorizedKeyring to be used 
by
+  # yast2-users module (which is mainly written in Perl).
+  class SSHAuthorizedKeysClass < Module
+    include Logger
+
+    attr_reader :keyring
+
+    def main
+      reset
+    end
+
+    # Read keys from a given home directory
+    #
+    # @see Yast::Users::SSHAuthorizedKeyring#read_keys
+    def read_keys(home)
+      keyring.read_keys(home)
+    end
+
+    # Write keys to a given home directory
+    #
+    # @see Yast::Users::SSHAuthorizedKeyring#write_keys
+    def write_keys(home)
+      keyring.write_keys(home)
+    rescue Users::SSHAuthorizedKeyring::HomeDoesNotExist => e
+      log.warn(e.message)
+      Report.Warning(
+        # TRANSLATORS: '%s' is a directory path
+        format(_("Home directory '%s' does not exist\n" \
+                 "so authorized keys will not be written."), e.path)
+      )
+    rescue Users::SSHAuthorizedKeyring::NotRegularSSHDirectory => e
+      log.warn(e.message)
+      Report.Warning(
+        # TRANSLATORS: '%s' is a directory path
+        format(_("'%s' exists but it is not a directory. It might be\n" \
+                 "a security issue so authorized keys will not\n" \
+                 "be written."), e.path)
+      )
+    rescue Users::SSHAuthorizedKeyring::NotRegularAuthorizedKeysFile => e
+      log.warn(e.message)
+      Report.Warning(
+        # TRANSLATORS: '%s' is a directory path
+        format(_("'%s' exists but it is not a file. It might be\n" \
+                 "a security issue so authorized keys will not\n" \
+                 "be written."), e.path)
+      )
+    rescue Users::SSHAuthorizedKeyring::CouldNotCreateSSHDirectory => e
+      log.warn(e.message)
+      Report.Warning(
+        Message.UnableToCreateDirectory(e.path) + "\n" +
+          _("Authorized keys will not be written.")
+      )
+    end
+
+    # Add a list of authorized keys for a given home directory
+    #
+    # @param path [String] User's home directory
+    # @param authorized_keys [Array<Hash|String>]
+    # @return [Boolean] +true+ if some key was imported; +false+ otherwise.
+    def import_keys(home, keys)
+      !keyring.add_keys(home, keys).empty?
+    end
+
+    # Return a hash representation of the authorized keys
+    #
+    # To be used while exporting the AutoYaST profile.
+    #
+    # @param [String] Home directory where the authorized keys are located
+    # @return [Array<Hash>] Authorized keys for the given home
+    def export_keys(home)
+      keyring[home]
+    end
+
+    # Initializes the module
+    def reset
+      @keyring = Users::SSHAuthorizedKeyring.new
+    end
+
+    publish function: :import_keys, type: "boolean (string, list)"
+    publish function: :read_keys, type: "boolean (string)"
+    publish function: :write_keys, type: "boolean (string)"
+    publish function: :export_keys, type: "list<map> (string)"
+  end
+
+  SSHAuthorizedKeys = SSHAuthorizedKeysClass.new
+  SSHAuthorizedKeys.main
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/src/modules/Users.pm 
new/yast2-users-3.1.60/src/modules/Users.pm
--- old/yast2-users-3.1.57/src/modules/Users.pm 2016-09-02 16:36:17.000000000 
+0200
+++ new/yast2-users-3.1.60/src/modules/Users.pm 2016-09-21 16:21:01.000000000 
+0200
@@ -245,6 +245,7 @@
 YaST::YCP::Import ("UsersRoutines");
 YaST::YCP::Import ("UsersSimple");
 YaST::YCP::Import ("UsersUI");
+YaST::YCP::Import ("SSHAuthorizedKeys");
 
 ##-------------------------------------------------------------------------
 ##----------------- various routines --------------------------------------
@@ -4058,6 +4059,16 @@
     }
 }
 
+sub WriteAuthorizedKeys {
+    foreach my $username (keys %{$modified_users{"local"}}) {
+        my %user       = %{$modified_users{"local"}{$username}};
+        if ($user{"modified"} == "imported") {
+            # Write authorized keys to user's home (FATE#319471)
+            SSHAuthorizedKeys->write_keys($user{"homeDirectory"});
+        }
+    }
+}
+
 ##------------------------------------
 # execute USERDEL_PRECMD scripts for users which should be deleted
 sub PreDeleteUsers {
@@ -4506,6 +4517,8 @@
                                $mode   = $user{"home_mode"};
                            }
                            UsersRoutines->ChmodHome($home, $mode);
+                           # Write authorized keys to user's home (FATE#319471)
+                           SSHAuthorizedKeys->write_keys($home);
                        }
                    }
                    Syslog->Log ("User added by YaST: name=$username, uid=$uid, 
gid=$gid, home=$home");
@@ -4558,6 +4571,9 @@
            }
        }
     }
+
+    if (Mode->autoinst() || Mode->autoupgrade() || Mode->config()) { 
WriteAuthorizedKeys(); }
+
     if (%users_with_crypted_dir) {
         unless (Package->Install ("cryptconfig"))
         {
@@ -5959,6 +5975,11 @@
        $ret{"shadowLastChange"} eq "") {
        $ret{"shadowLastChange"}        = LastChangeIsNow ();
     }
+
+    # Import authorized keys from profile (FATE#319471)
+    if ($user->{"authorized_keys"} && $ret{"homeDirectory"}) {
+      SSHAuthorizedKeys->import_keys($ret{"homeDirectory"}, 
$user->{"authorized_keys"});
+    }
     return \%ret;
 }
 
@@ -6463,6 +6484,13 @@
     if (%user_shadow) {
        $ret{"password_settings"}       = \%user_shadow;
     }
+    if ($user->{"homeDirectory"}) {
+        # Export authorized keys to profile (FATE#319471)
+        my $keys = SSHAuthorizedKeys->export_keys($user->{"homeDirectory"});
+        if (@$keys) {
+            $ret{"authorized_keys"} = $keys;
+        }
+    }
     return \%ret;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/src/modules/UsersLDAP.pm 
new/yast2-users-3.1.60/src/modules/UsersLDAP.pm
--- old/yast2-users-3.1.57/src/modules/UsersLDAP.pm     2016-09-02 
16:36:17.000000000 +0200
+++ new/yast2-users-3.1.60/src/modules/UsersLDAP.pm     2016-09-21 
16:21:01.000000000 +0200
@@ -1144,7 +1144,7 @@
     if (!defined $data->{"uidNumber"}) {
        @internal       = @group_internal_keys;
     }
-    foreach my $key (keys %{$data}) {
+    foreach my $key (sort keys %{$data}) {
        my $val = $data->{$key};
        if (contains (\@internal, $key, 1)) {
            next;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/src/modules/UsersPasswd.pm 
new/yast2-users-3.1.60/src/modules/UsersPasswd.pm
--- old/yast2-users-3.1.57/src/modules/UsersPasswd.pm   2016-09-02 
16:36:17.000000000 +0200
+++ new/yast2-users-3.1.60/src/modules/UsersPasswd.pm   2016-09-21 
16:21:01.000000000 +0200
@@ -33,6 +33,7 @@
 
 YaST::YCP::Import ("FileUtils");
 YaST::YCP::Import ("SCR");
+YaST::YCP::Import ("SSHAuthorizedKeys");
 
 #---------------------------------------------------------------------
 #--------------------------------------------------------- definitions
@@ -299,6 +300,13 @@
     return 1;
 }
 
+# Read authorized keys from user's home (FATE#319471)
+sub read_authorized_keys {
+    foreach my $user (values %{$users{"local"}}) {
+      SSHAuthorizedKeys->read_keys($user->{"homeDirectory"});
+    }
+}
+
 # actually read /etc/passwd and save into internal structure
 sub read_passwd {
 
@@ -518,6 +526,7 @@
     }
     if (read_shadow () && read_group ()) {
        $ret = read_passwd ();
+       read_authorized_keys();
     }
     $initialized       = $ret;
     return $ret;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/test/Makefile.am 
new/yast2-users-3.1.60/test/Makefile.am
--- old/yast2-users-3.1.57/test/Makefile.am     2016-09-02 16:36:17.000000000 
+0200
+++ new/yast2-users-3.1.60/test/Makefile.am     2016-09-21 16:21:01.000000000 
+0200
@@ -1,6 +1,10 @@
 # Tests for users
 TESTS = \
-  users_finish_test.rb
+  users_finish_test.rb \
+  lib/users/ca_password_validator_test.rb \
+  lib/users/encryption_method_test.rb \
+  lib/users/ssh_authorized_keys_file_test.rb \
+  lib/users/users_database_test.rb
 
 TEST_EXTENSIONS = .rb
 RB_LOG_COMPILER = rspec
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-users-3.1.57/test/fixtures/home/user1/.ssh/authorized_keys 
new/yast2-users-3.1.60/test/fixtures/home/user1/.ssh/authorized_keys
--- old/yast2-users-3.1.57/test/fixtures/home/user1/.ssh/authorized_keys        
1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-users-3.1.60/test/fixtures/home/user1/.ssh/authorized_keys        
2016-09-21 16:21:01.000000000 +0200
@@ -0,0 +1,2 @@
+environment="PATH=/usr/local/bin:$PATH",command="/srv/logon.sh $USER" ssh-rsa 
AAAAB3NzaC1yc2EAAAADAQABAAABAQCpZC8ctjmn90B/MxLOdSjYM3Yl3qd+BhTWYdBNgO3B1fJ1JSegTgCpDM0krMHqd/OAslW5H3MRED7g7g9WkKZh5xTMGvH56yRitJySfSiK8uSxCu6Jg7NM11kqOs5/RwycHO8955QrEYyiWOx80unD+CBJxGEZCOu/DH3ca4yEigAt2HSuC8NPicmRJWua6IbDa+VSICvdOTdFTM8izScSd5WBFH1ULz0bBfLnyi/pIiMjuHB69AN4gsUGYgKjzUsnufKli+DmzACgVWTdQ3Ukax/4/wgXFMr3KsDNpTbn7ZZOKzPpIXpzlP9AwbHQdym6J2NAPYV+DDY3Kcr/vql9
 [email protected]
+ssh-rsa 
AAAAB3NzaC1yc2EAAAADAQABAAABAQCZXHfWaMch5VrgbogbW8lVuuwYCxQrgh00fF0V+GBBc0F6sux+WFlIENRLDNDSGBWol1X9LnbpgElzgM/PDX/3Uj+p+LVkt7sTk4k3tQQqFkrHEC+1TFnRk22AB4Xcw5KQ/bQnw1Cu0IfA/8c3c3Eh56WNiNi6F/bUeYKsdLLueGC/wKO/dCjM5xsLy/tXALrH0Y4NKbIZauM4BcEnZ7Cl6Wzl1AT/Mg+UK7bD8onufNd1l2w0rC0+BEy8VtBBobicp/Wv3nKkumKpNzP6jvpFE8CKiGx/fYzH/pLfe7bxEfBkKyR7A4gGWv6GHUaCYV+T+nac2ctWLLne1uQhRZcj
 [email protected]
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-users-3.1.57/test/fixtures/home/user2/.ssh/authorized_keys 
new/yast2-users-3.1.60/test/fixtures/home/user2/.ssh/authorized_keys
--- old/yast2-users-3.1.57/test/fixtures/home/user2/.ssh/authorized_keys        
1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-users-3.1.60/test/fixtures/home/user2/.ssh/authorized_keys        
2016-09-21 16:21:01.000000000 +0200
@@ -0,0 +1 @@
+# Prueba
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/test/fixtures/users_no_error.yml 
new/yast2-users-3.1.60/test/fixtures/users_no_error.yml
--- old/yast2-users-3.1.57/test/fixtures/users_no_error.yml     2016-09-02 
16:36:17.000000000 +0200
+++ new/yast2-users-3.1.60/test/fixtures/users_no_error.yml     2016-09-21 
16:21:01.000000000 +0200
@@ -26,4 +26,9 @@
     user_password: suse
     fullname: user_no_uid2
     shell: /usr/bin/zsh
-    encrypted: true
\ No newline at end of file
+    encrypted: true
+    authorized_keys:
+      - comment: [email protected]
+        keytype: ssh-rsa
+        content: abc123
+        options: tunnel="0"
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-users-3.1.57/test/lib/users/ca_password_validator_test.rb 
new/yast2-users-3.1.60/test/lib/users/ca_password_validator_test.rb
--- old/yast2-users-3.1.57/test/lib/users/ca_password_validator_test.rb 
2016-09-02 16:36:17.000000000 +0200
+++ new/yast2-users-3.1.60/test/lib/users/ca_password_validator_test.rb 
2016-09-21 16:21:01.000000000 +0200
@@ -1,4 +1,4 @@
-#! /usr/bin/rspec
+#! /usr/bin/env rspec
 # Copyright (c) 2016 SUSE LLC.
 #  All Rights Reserved.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-users-3.1.57/test/lib/users/encryption_method.rb 
new/yast2-users-3.1.60/test/lib/users/encryption_method.rb
--- old/yast2-users-3.1.57/test/lib/users/encryption_method.rb  2016-09-02 
16:36:17.000000000 +0200
+++ new/yast2-users-3.1.60/test/lib/users/encryption_method.rb  1970-01-01 
01:00:00.000000000 +0100
@@ -1,60 +0,0 @@
-#! /usr/bin/rspec
-# Copyright (c) 2016 SUSE LLC.
-#  All Rights Reserved.
-
-#  This program is free software; you can redistribute it and/or
-#  modify it under the terms of version 2 or 3 of the GNU General
-#  Public License as published by the Free Software Foundation.
-
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
-#  GNU General Public License for more details.
-
-#  You should have received a copy of the GNU General Public License
-#  along with this program; if not, contact SUSE LLC.
-
-#  To contact SUSE about this file by physical or electronic mail,
-#  you may find current contact information at www.suse.com
-
-require_relative "../../test_helper"
-require "users/encryption_method"
-Yast.import "UsersSimple"
-
-describe Users::EncryptionMethod do
-  before do
-    allow(Yast::UsersSimple).to receive(:EncryptionMethod).and_return 
(current_method)
-  end
-
-  subject { Users::EncryptionMethod }
-
-  describe ".current" do
-    context "if an unknown method is returned by UsersSimple" do
-      let(:current_method) { "plain" }
-
-      it "raises an exception" do
-        expect { subject.current }.to raise_error 
Users::EncryptionMethod::NotFoundError
-      end
-    end
-
-    context "if a valid method is returned by UsersSimple" do
-      let(:current_method) { "sha256" }
-
-      it "returns the corresponding object" do
-        expect(subject.current).to eq subject.new("sha256")
-      end
-    end
-  end
-
-  describe "#current?" do
-    let(:current_method) { "des" }
-
-    it "returns true if the method is the current one" do
-      expect(subject.new("des").current?).to eq true
-    end
-
-    it "returns false if the method is not the current one" do
-      expect(subject.new("sha512").current?).to eq false
-    end
-  end
-end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-users-3.1.57/test/lib/users/encryption_method_test.rb 
new/yast2-users-3.1.60/test/lib/users/encryption_method_test.rb
--- old/yast2-users-3.1.57/test/lib/users/encryption_method_test.rb     
1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-users-3.1.60/test/lib/users/encryption_method_test.rb     
2016-09-21 16:21:01.000000000 +0200
@@ -0,0 +1,60 @@
+#! /usr/bin/env rspec
+# Copyright (c) 2016 SUSE LLC.
+#  All Rights Reserved.
+
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of version 2 or 3 of the GNU General
+#  Public License as published by the Free Software Foundation.
+
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
+#  GNU General Public License for more details.
+
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, contact SUSE LLC.
+
+#  To contact SUSE about this file by physical or electronic mail,
+#  you may find current contact information at www.suse.com
+
+require_relative "../../test_helper"
+require "users/encryption_method"
+Yast.import "UsersSimple"
+
+describe Users::EncryptionMethod do
+  before do
+    allow(Yast::UsersSimple).to receive(:EncryptionMethod).and_return 
(current_method)
+  end
+
+  subject { Users::EncryptionMethod }
+
+  describe ".current" do
+    context "if an unknown method is returned by UsersSimple" do
+      let(:current_method) { "plain" }
+
+      it "raises an exception" do
+        expect { subject.current }.to raise_error 
Users::EncryptionMethod::NotFoundError
+      end
+    end
+
+    context "if a valid method is returned by UsersSimple" do
+      let(:current_method) { "sha256" }
+
+      it "returns the corresponding object" do
+        expect(subject.current).to eq subject.new("sha256")
+      end
+    end
+  end
+
+  describe "#current?" do
+    let(:current_method) { "des" }
+
+    it "returns true if the method is the current one" do
+      expect(subject.new("des").current?).to eq true
+    end
+
+    it "returns false if the method is not the current one" do
+      expect(subject.new("sha512").current?).to eq false
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-users-3.1.57/test/lib/users/local_password_test.rb 
new/yast2-users-3.1.60/test/lib/users/local_password_test.rb
--- old/yast2-users-3.1.57/test/lib/users/local_password_test.rb        
2016-09-02 16:36:17.000000000 +0200
+++ new/yast2-users-3.1.60/test/lib/users/local_password_test.rb        
2016-09-21 16:21:01.000000000 +0200
@@ -1,4 +1,4 @@
-#! /usr/bin/rspec
+#! /usr/bin/env rspec
 # Copyright (c) 2016 SUSE LLC.
 #  All Rights Reserved.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-users-3.1.57/test/lib/users/ssh_authorized_keyring_test.rb 
new/yast2-users-3.1.60/test/lib/users/ssh_authorized_keyring_test.rb
--- old/yast2-users-3.1.57/test/lib/users/ssh_authorized_keyring_test.rb        
1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-users-3.1.60/test/lib/users/ssh_authorized_keyring_test.rb        
2016-09-21 16:21:01.000000000 +0200
@@ -0,0 +1,210 @@
+#!/usr/bin/env rspec
+# Copyright (c) 2016 SUSE LLC.
+#  All Rights Reserved.
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of version 2 or 3 of the GNU General
+#  Public License as published by the Free Software Foundation.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, contact SUSE LLC.
+#
+#  To contact SUSE about this file by physical or electronic mail,
+#  you may find current contact information at www.suse.com
+
+require_relative "../../test_helper"
+require "users/ssh_authorized_keyring"
+require "tmpdir"
+
+describe Yast::Users::SSHAuthorizedKeyring do
+  subject(:keyring) { Yast::Users::SSHAuthorizedKeyring.new }
+
+  describe "#empty?" do
+    context "when keyring is empty" do
+      it "returns true" do
+        expect(keyring.empty?).to eq(true)
+      end
+    end
+
+    context "when keyring is not empty" do
+      before { keyring.add_keys("/home/user", ["ssh-rsa 123ABC"]) }
+
+      it "returns false" do
+        expect(keyring.empty?).to eq(false)
+      end
+    end
+  end
+
+  describe "#read_keys" do
+    context "if some keys are present in the given home directory" do
+      let(:home) { FIXTURES_PATH.join("home", "user1").to_s }
+
+      it "returns true" do
+        expect(keyring.read_keys(home)).to eq(true)
+      end
+
+      it "registers defined keys" do
+        keyring.read_keys(home)
+        expect(keyring).to_not be_empty
+      end
+    end
+
+    context "if no keys are present in the home directory" do
+      let(:home) { FIXTURES_PATH.join("home", "user2").to_s }
+
+      it "returns false" do
+        expect(keyring.read_keys(home)).to eq(false)
+      end
+
+      it "does not register any key" do
+        keyring.read_keys(home)
+        expect(keyring).to be_empty
+      end
+    end
+
+    context "if authorized keys file does not exist" do
+      let(:home) { FIXTURES_PATH.join("home", "other").to_s }
+
+      it "returns false" do
+        expect(keyring.read_keys(home)).to eq(false)
+      end
+
+      it "does not register any key" do
+        keyring.read_keys(home)
+        expect(keyring).to be_empty
+      end
+    end
+  end
+
+  describe "#write_keys" do
+    let(:tmpdir) { Dir.mktmpdir }
+    let(:home) { File.join(tmpdir, "/home/user") }
+    let(:file) { double("file", save: true) }
+    let(:ssh_dir) { File.join(home, ".ssh") }
+    let(:key) { "ssh-rsa 123ABC" }
+    let(:authorized_keys_path) { File.join(home, ".ssh", "authorized_keys") }
+
+    before { FileUtils.mkdir_p(home) }
+    after { FileUtils.rm_rf(tmpdir) if File.exist?(tmpdir) }
+
+    context "if no keys are registered for the given home" do
+      it "returns false" do
+        expect(keyring.write_keys(home)).to eq(false)
+      end
+
+      it "does not try to write the keys" do
+        expect(file).to_not receive(:save)
+        keyring.write_keys(home)
+      end
+    end
+
+    context "if some keys are registered for the given home" do
+      let(:uid) { 1001 }
+      let(:gid) { 101 }
+      let(:home_dir_exists) { true }
+      let(:ssh_dir_exists) { false }
+
+      before do
+        allow(Yast::SCR).to receive(:Execute).and_call_original
+        allow(Yast::SCR).to receive(:Read).and_call_original
+        allow(Yast::FileUtils).to receive(:Exists).and_call_original
+        allow(Yast::FileUtils).to 
receive(:Exists).with(ssh_dir).and_return(ssh_dir_exists)
+        allow(Yast::FileUtils).to 
receive(:Exists).with(home).and_return(home_dir_exists)
+        allow(Yast::FileUtils).to receive(:IsDirectory).with(ssh_dir)
+          .and_return(true)
+        keyring.add_keys(home, [key])
+      end
+
+      it "writes the keys and returns true" do
+        expect(keyring.write_keys(home)).to eq(true)
+        expect(File).to exist(authorized_keys_path)
+      end
+
+      it "SSH directory and authorized_keys inherits owner/group from home" do
+        allow(Yast::FileUtils).to 
receive(:GetOwnerUserID).with(home).and_return(uid)
+        allow(Yast::FileUtils).to 
receive(:GetOwnerGroupID).with(home).and_return(gid)
+        expect(Yast::FileUtils).to receive(:Chown).with("#{uid}:#{gid}", 
ssh_dir, false)
+        expect(Yast::FileUtils).to receive(:Chown).with("#{uid}:#{gid}", 
authorized_keys_path, false)
+
+        keyring.write_keys(home)
+      end
+
+      it "sets SSH directory permissions to 0700" do
+        keyring.write_keys(home)
+        mode = File.stat(ssh_dir).mode.to_s(8)
+        expect(mode).to eq("40700")
+      end
+
+      it "sets authorized_keys permissions to 0600" do
+        keyring.write_keys(home)
+        mode = File.stat(authorized_keys_path).mode.to_s(8)
+        expect(mode).to eq("100600")
+      end
+
+      context "when home directory does not exist" do
+        let(:home_dir_exists) { false }
+
+        it "raises a HomeDoesNotExist exception and does not write 
authorized_keys" do
+          expect(Yast::Users::SSHAuthorizedKeysFile).to_not receive(:new)
+          expect { keyring.write_keys(home) }
+            .to 
raise_error(Yast::Users::SSHAuthorizedKeyring::HomeDoesNotExist)
+        end
+      end
+
+      context "when SSH directory could not be created" do
+        it "raises a CouldNotCreateSSHDirectory exception and does not write 
authorized_keys" do
+          expect(Yast::Users::SSHAuthorizedKeysFile).to_not receive(:new)
+          expect(Yast::SCR).to receive(:Execute)
+            .with(Yast::Path.new(".target.mkdir"), anything)
+            .and_return(false)
+          expect { keyring.write_keys(home) }
+            .to 
raise_error(Yast::Users::SSHAuthorizedKeyring::CouldNotCreateSSHDirectory)
+        end
+      end
+
+      context "when SSH directory is not a regular directory" do
+        let(:ssh_dir_exists) { true }
+
+        it "raises a NotRegularSSHDirectory and does not write 
authorized_keys" do
+          allow(Yast::FileUtils).to receive(:IsDirectory).with(ssh_dir)
+            .and_return(false)
+          expect(Yast::Users::SSHAuthorizedKeysFile).to_not receive(:new)
+          expect { keyring.write_keys(home) }
+            .to 
raise_error(Yast::Users::SSHAuthorizedKeyring::NotRegularSSHDirectory)
+        end
+      end
+
+      context "when SSH directory already exists" do
+        let(:ssh_dir_exists) { true }
+
+        it "does not create the directory" do
+          allow(Yast::FileUtils).to receive(:IsDirectory).with(ssh_dir)
+            .and_return(true)
+          expect(Yast::SCR).to_not receive(:Execute)
+            .with(Yast::Path.new(".target.mkdir"), anything)
+          keyring.write_keys(home)
+        end
+      end
+
+      context "when authorized_keys is not a regular file" do
+        let(:ssh_dir_exists) { true }
+        let(:file) { double("file") }
+
+        it "raises a NotRegularAuthorizedKeysFile" do
+          allow(Yast::Users::SSHAuthorizedKeysFile).to 
receive(:new).and_return(file)
+          allow(file).to receive(:keys=)
+          allow(file).to receive(:save)
+            .and_raise(Yast::Users::SSHAuthorizedKeysFile::NotRegularFile)
+
+          expect { keyring.write_keys(home) }
+            .to 
raise_error(Yast::Users::SSHAuthorizedKeyring::NotRegularAuthorizedKeysFile)
+        end
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-users-3.1.57/test/lib/users/ssh_authorized_keys_file_test.rb 
new/yast2-users-3.1.60/test/lib/users/ssh_authorized_keys_file_test.rb
--- old/yast2-users-3.1.57/test/lib/users/ssh_authorized_keys_file_test.rb      
1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-users-3.1.60/test/lib/users/ssh_authorized_keys_file_test.rb      
2016-09-21 16:21:01.000000000 +0200
@@ -0,0 +1,149 @@
+#!/usr/bin/env rspec
+# Copyright (c) 2016 SUSE LLC.
+#  All Rights Reserved.
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of version 2 or 3 of the GNU General
+#  Public License as published by the Free Software Foundation.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, contact SUSE LLC.
+#
+#  To contact SUSE about this file by physical or electronic mail,
+#  you may find current contact information at www.suse.com
+require_relative "../../test_helper"
+require "users/ssh_authorized_keys_file"
+
+describe Yast::Users::SSHAuthorizedKeysFile do
+  subject(:file) { Yast::Users::SSHAuthorizedKeysFile.new(path) }
+  let(:path) { FIXTURES_PATH.join("home", "user1", ".ssh", "authorized_keys") }
+
+  describe "#keys" do
+    context "when file is empty" do
+      let(:path) { FIXTURES_PATH.join("home", "user2", ".ssh", 
"authorized_keys") }
+
+      it "returns an empty array" do
+        expect(subject.keys).to eq([])
+      end
+    end
+
+    context "when file contains some keys" do
+      let(:path) { FIXTURES_PATH.join("home", "user1", ".ssh", 
"authorized_keys") }
+
+      it "returns the keys that are present in the file" do
+        first, second = subject.keys
+        expect(first).to match(/environment=.+/)
+        expect(second).to match(/ssh-rsa/)
+      end
+    end
+
+    context "when file does not exist" do
+      let(:path) { FIXTURES_PATH.join("non-existent-file") }
+
+      it "returns an empty array" do
+        expect(subject.keys).to eq([])
+      end
+    end
+  end
+
+  describe "#keys=" do
+    let(:key) { "ssh-dsa 123ABC" }
+
+    it "sets file keys" do
+      file.keys = [key]
+      expect(file.keys).to eq([key])
+    end
+  end
+
+  describe "#save" do
+    let(:key0) { "ssh-dsa 123ABC" }
+    let(:key1) { "ssh-rsa 456DEF" }
+    let(:expected_content) { "ssh-dsa 123ABC\nssh-rsa 456DEF\n" }
+
+    let(:path) { "/tmp/home/user" }
+    let(:dir)  { File.dirname(path) }
+    let(:file_exists) { false }
+
+    before do
+      allow(Yast::FileUtils).to receive(:Exists).with(dir)
+        .and_return(dir_exists)
+      allow(Yast::FileUtils).to receive(:Exists).with(path)
+        .and_return(file_exists)
+    end
+
+    context "if the directory exists" do
+      let(:dir_exists) { true }
+
+      it "creates the file with the registered keys and returns true" do
+        expect(Yast::SCR).to receive(:Write)
+          .with(Yast::Path.new(".target.string"), path, expected_content)
+        file.keys = [key0, key1]
+        file.save
+      end
+
+      context "and the file exists and it is a regular one" do
+        let(:file_exists) { true }
+
+        it "updates the file with the registered keys and returns true" do
+          allow(Yast::FileUtils).to receive(:IsFile).with(path)
+            .and_return(true)
+
+          expect(Yast::SCR).to receive(:Write)
+            .with(Yast::Path.new(".target.string"), path, expected_content)
+          file.keys = [key0, key1]
+          file.save
+        end
+      end
+
+      context "and the file exists but it is not a regular one" do
+        let(:file_exists) { true }
+
+        it "raises NotRegularFile exception and does not update the file" do
+          allow(Yast::FileUtils).to receive(:IsFile).with(path)
+            .and_return(false)
+
+          expect(Yast::SCR).to_not receive(:Write)
+            .with(Yast::Path.new(".target.string"), anything)
+          file.keys = [key0, key1]
+          expect { file.save }.to 
raise_error(Yast::Users::SSHAuthorizedKeysFile::NotRegularFile)
+        end
+      end
+    end
+
+    context "if the directory does not exist" do
+      let(:dir_exists) { false }
+
+      it "returns false" do
+        file.keys = [key0, key1]
+        expect(file.save).to eq(false)
+      end
+    end
+  end
+
+  describe "#add_key" do
+    let(:key) { "ssh-dsa 123ABC" }
+
+    context "when the contains keys" do
+      let(:path) { FIXTURES_PATH.join("home", "user1", ".ssh", 
"authorized_keys") }
+
+      it "adds the new key" do
+        file.add_key(key)
+        expect(file.keys).to include(key)
+      end
+    end
+
+    context "when the file does not contain keys" do
+      let(:path) { FIXTURES_PATH.join("home", "user2", ".ssh", 
"authorized_keys") }
+
+      it "adds the new key" do
+        file.add_key(key)
+        expect(file.keys).to eq([key])
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-users-3.1.57/test/lib/users/users_database_test.rb 
new/yast2-users-3.1.60/test/lib/users/users_database_test.rb
--- old/yast2-users-3.1.57/test/lib/users/users_database_test.rb        
2016-09-02 16:36:17.000000000 +0200
+++ new/yast2-users-3.1.60/test/lib/users/users_database_test.rb        
2016-09-21 16:21:01.000000000 +0200
@@ -1,4 +1,4 @@
-#! /usr/bin/rspec
+#! /usr/bin/env rspec
 # Copyright (c) 2016 SUSE LLC.
 #  All Rights Reserved.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/test/ssh_authorized_keys_test.rb 
new/yast2-users-3.1.60/test/ssh_authorized_keys_test.rb
--- old/yast2-users-3.1.57/test/ssh_authorized_keys_test.rb     1970-01-01 
01:00:00.000000000 +0100
+++ new/yast2-users-3.1.60/test/ssh_authorized_keys_test.rb     2016-09-21 
16:21:01.000000000 +0200
@@ -0,0 +1,129 @@
+#!/usr/bin/env rspec
+# Copyright (c) 2016 SUSE LLC.
+#  All Rights Reserved.
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of version 2 or 3 of the GNU General
+#  Public License as published by the Free Software Foundation.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, contact SUSE LLC.
+#
+#  To contact SUSE about this file by physical or electronic mail,
+#  you may find current contact information at www.suse.com
+
+require_relative "test_helper"
+require "users/ssh_authorized_keyring"
+require "tmpdir"
+
+Yast.import "SSHAuthorizedKeys"
+Yast.import "Report"
+
+describe Yast::SSHAuthorizedKeys do
+  subject(:ssh_authorized_keys) { Yast::SSHAuthorizedKeys }
+
+  let(:valid_key_spec) { double("valid_key") }
+  let(:invalid_key_spec) { double("invalid_key") }
+  let(:home) { "/home/user" }
+  let(:ssh_dir) { File.join(home, ".ssh") }
+  let(:authorized_keys_path) { File.join("ssh_dir", ".authorized_keys") }
+  let(:key) { double("key") }
+  let(:keys) { [key] }
+
+  before { subject.reset }
+
+  describe "#import_keys" do
+    it "imports keys into the keyring" do
+      expect(subject.keyring).to receive(:add_keys).with(home, keys)
+        .and_return(keys)
+      subject.import_keys(home, keys)
+    end
+
+    it "returns true if some key was imported" do
+      allow(subject.keyring).to receive(:add_keys).with(home, keys)
+        .and_return(keys)
+      expect(subject.import_keys(home, keys)).to eq(true)
+    end
+
+    it "returns false if no key was imported" do
+      allow(subject.keyring).to receive(:add_keys).with(home, keys)
+        .and_return([])
+      expect(subject.import_keys(home, keys)).to eq(false)
+    end
+  end
+
+  describe "#export_keys" do
+    context "when some key was added" do
+      before { subject.import_keys(home, keys) }
+
+      it "returns an array with added keys" do
+        expect(subject.export_keys(home)).to eq(keys)
+      end
+    end
+
+    context "when no key was added" do
+      it "returns an empty array" do
+        expect(subject.export_keys(home)).to eq([])
+      end
+    end
+  end
+
+  describe "#write_keys" do
+    context "when home directory does not exists" do
+      let(:exception) do
+        Yast::Users::SSHAuthorizedKeyring::HomeDoesNotExist.new(home)
+      end
+
+      it "shows an error message" do
+        allow(subject.keyring).to receive(:write_keys).and_raise(exception)
+        expect(Yast::Report).to receive(:Warning)
+          .with(/'#{home}' does not exist/)
+        subject.write_keys(home)
+      end
+    end
+
+    context "SSH directory is not a directory" do
+      let(:exception) do
+        Yast::Users::SSHAuthorizedKeyring::NotRegularSSHDirectory.new(ssh_dir)
+      end
+
+      it "shows an error message" do
+        allow(subject.keyring).to receive(:write_keys).and_raise(exception)
+        expect(Yast::Report).to receive(:Warning)
+          .with(/'#{ssh_dir}' exists but it is not a directory/)
+        subject.write_keys(home)
+      end
+    end
+
+    context "SSH directory could not be created" do
+      let(:exception) do
+        
Yast::Users::SSHAuthorizedKeyring::CouldNotCreateSSHDirectory.new(ssh_dir)
+      end
+
+      it "shows an error message" do
+        allow(subject.keyring).to receive(:write_keys).and_raise(exception)
+        expect(Yast::Report).to receive(:Warning)
+          .with(/not create directory '#{ssh_dir}'/)
+        subject.write_keys(home)
+      end
+    end
+
+    context "authorized_keys exists but it's not a regular file" do
+      let(:exception) do
+        
Yast::Users::SSHAuthorizedKeyring::NotRegularAuthorizedKeysFile.new(authorized_keys_path)
+      end
+
+      it "shows an error message" do
+        allow(subject.keyring).to receive(:write_keys).and_raise(exception)
+        expect(Yast::Report).to receive(:Warning)
+          .with(/'#{authorized_keys_path}' exists but it is not a file/)
+        subject.write_keys(home)
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/test/test_helper.rb 
new/yast2-users-3.1.60/test/test_helper.rb
--- old/yast2-users-3.1.57/test/test_helper.rb  2016-09-02 16:36:17.000000000 
+0200
+++ new/yast2-users-3.1.60/test/test_helper.rb  2016-09-21 16:21:01.000000000 
+0200
@@ -20,6 +20,10 @@
 src_path = File.expand_path("../../src", __FILE__)
 ENV["Y2DIR"] = src_path
 
+# make sure we run the tests in English locale
+# (some tests check the output which is marked for translation)
+ENV["LC_ALL"] = "en_US.UTF-8"
+
 require "yast"
 require "pathname"
 require "yast/rspec"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/testsuite/modules/Ldap.rb 
new/yast2-users-3.1.60/testsuite/modules/Ldap.rb
--- old/yast2-users-3.1.57/testsuite/modules/Ldap.rb    1970-01-01 
01:00:00.000000000 +0100
+++ new/yast2-users-3.1.60/testsuite/modules/Ldap.rb    2016-09-21 
16:21:01.000000000 +0200
@@ -0,0 +1,9 @@
+require "yast"
+module Yast
+  # This exists because it is hard to use RSpec mocks for code
+  # that goes through Perl (like UsersLdap.pm)
+  class LdapClass < Module
+    Builtins.y2milestone("Using a mock Ldap module")
+  end
+  Ldap = LdapClass.new
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/testsuite/tests/ConvertMap.out 
new/yast2-users-3.1.60/testsuite/tests/ConvertMap.out
--- old/yast2-users-3.1.57/testsuite/tests/ConvertMap.out       2016-09-02 
16:36:18.000000000 +0200
+++ new/yast2-users-3.1.60/testsuite/tests/ConvertMap.out       2016-09-21 
16:21:01.000000000 +0200
@@ -1,24 +1,31 @@
 Dump   ==========================================================
 Dump   --------- user (loginshell is changed):
 Dump    $["dn":"uid=test2,ou=people,dc=suse,dc=cz", "encrypted":true, 
"gecos":"test", "gidNumber":100, "grouplist":$["audio":1], "groupname":"users", 
"loginShell":"/bin/csh", "modified":"edited", "objectClass":["inetOrgPerson", 
"posixAccount", "shadowAccount", "top"], "org_uid":"test2", 
"org_uidnumber":11111, "org_user":$["dn":"uid=test2,ou=people,dc=suse,dc=cz", 
"gecos":"test", "gidNumber":100, "grouplist":$["audio":1], "groupname":"users", 
"loginShell":"/bin/bash", "objectClass":["inetOrgPerson", "posixAccount", 
"shadowAccount", "top"], "type":"ldap", "uid":"test2", "uidNumber":11111, 
"userPassword":"{crypt}IVj2W92x/IuFs"], "plugins":["UsersPluginLDAPAll"], 
"type":"ldap", "uid":"test2", "uidNumber":11111, 
"userPassword":"{crypt}IVj2W92x/IuFs", "what":"edit_user"]
+Read   .ldap.schema.at $["name":"loginShell"] $["usage":1]
 Return $["loginShell":"/bin/csh"]
 Dump   --------- converted :
 Dump    $["loginShell":"/bin/csh"]
 Dump   ==========================================================
 Dump   --------- user (new password):
 Dump    $["dn":"uid=test2,ou=people,dc=suse,dc=cz", "encrypted":true, 
"gecos":"test", "gidNumber":100, "grouplist":$["audio":1], "groupname":"users", 
"loginShell":"/bin/csh", "modified":"edited", "objectClass":["inetOrgPerson", 
"posixAccount", "shadowAccount", "top"], "org_uid":"test2", 
"org_uidnumber":11111, "org_user":$["dn":"uid=test2,ou=people,dc=suse,dc=cz", 
"gecos":"test", "gidNumber":100, "grouplist":$["audio":1], "groupname":"users", 
"loginShell":"/bin/bash", "objectClass":["inetOrgPerson", "posixAccount", 
"shadowAccount", "top"], "type":"ldap", "uid":"test2", "uidNumber":11111, 
"userPassword":"{crypt}IVj2W92x/IuFs"], "plugins":["UsersPluginLDAPAll"], 
"type":"ldap", "uid":"test2", "uidNumber":11111, "userPassword":"qqqqq", 
"what":"edit_user"]
+Read   .ldap.schema.at $["name":"userPassword"] $["usage":1]
 Return $["loginShell":"/bin/csh", "userPassword":"{crypt}qqqqq"]
 Dump   --------- converted :
 Dump    $["loginShell":"/bin/csh", "userPassword":"{crypt}qqqqq"]
 Dump   ==========================================================
 Dump   --------- user (new object class):
 Dump    $["dn":"uid=test2,ou=people,dc=suse,dc=cz", "encrypted":true, 
"gecos":"test", "gidNumber":100, "grouplist":$["audio":1], "groupname":"users", 
"loginShell":"/bin/csh", "modified":"edited", "objectClass":["inetOrgPerson", 
"posixAccount", "shadowAccount", "top", "sambaSamAccount"], "org_uid":"test2", 
"org_uidnumber":11111, "org_user":$["dn":"uid=test2,ou=people,dc=suse,dc=cz", 
"gecos":"test", "gidNumber":100, "grouplist":$["audio":1], "groupname":"users", 
"loginShell":"/bin/bash", "objectClass":["inetOrgPerson", "posixAccount", 
"shadowAccount", "top"], "type":"ldap", "uid":"test2", "uidNumber":11111, 
"userPassword":"{crypt}qqqqq"], "plugins":["UsersPluginLDAPAll"], 
"type":"ldap", "uid":"test2", "uidNumber":11111, "userPassword":"{crypt}qqqqq", 
"what":"edit_user"]
+Read   .ldap.schema.at $["name":"objectClass"] $["usage":1]
 Return $["loginShell":"/bin/csh", "objectClass":["inetOrgPerson", 
"posixAccount", "shadowAccount", "top", "sambaSamAccount"]]
 Dump   --------- converted :
 Dump    $["loginShell":"/bin/csh", "objectClass":["inetOrgPerson", 
"posixAccount", "shadowAccount", "top", "sambaSamAccount"]]
 Dump   ==========================================================
 Dump   --------- user (removed 'org_user' submap):
 Dump    $["dn":"uid=test2,ou=people,dc=suse,dc=cz", "encrypted":true, 
"gecos":"test", "gidNumber":100, "grouplist":$["audio":1], "groupname":"users", 
"loginShell":"/bin/csh", "modified":"edited", "objectClass":["inetOrgPerson", 
"posixAccount", "shadowAccount", "top", "sambaSamAccount"], "org_uid":"test2", 
"org_uidnumber":11111, "plugins":["UsersPluginLDAPAll"], "type":"ldap", 
"uid":"test2", "uidNumber":11111, "userPassword":"{crypt}qqqqq", 
"what":"edit_user"]
+Read   .ldap.schema.at $["name":"gecos"] $["usage":1]
+Read   .ldap.schema.at $["name":"gidNumber"] $["usage":1]
+Read   .ldap.schema.at $["name":"uid"] $["usage":1]
+Read   .ldap.schema.at $["name":"uidNumber"] $["usage":1]
 Return $["gecos":"test", "gidNumber":"100", "loginShell":"/bin/csh", 
"objectClass":["inetOrgPerson", "posixAccount", "shadowAccount", "top", 
"sambaSamAccount"], "uid":"test2", "uidNumber":"11111", 
"userPassword":"{crypt}qqqqq"]
 Dump   --------- converted :
 Dump    $["gecos":"test", "gidNumber":"100", "loginShell":"/bin/csh", 
"objectClass":["inetOrgPerson", "posixAccount", "shadowAccount", "top", 
"sambaSamAccount"], "uid":"test2", "uidNumber":"11111", 
"userPassword":"{crypt}qqqqq"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-users-3.1.57/testsuite/tests/ConvertMap.rb 
new/yast2-users-3.1.60/testsuite/tests/ConvertMap.rb
--- old/yast2-users-3.1.57/testsuite/tests/ConvertMap.rb        2016-09-02 
16:36:18.000000000 +0200
+++ new/yast2-users-3.1.60/testsuite/tests/ConvertMap.rb        2016-09-21 
16:21:01.000000000 +0200
@@ -21,6 +21,7 @@
         },
         "ldap"    => {
           "schema" => {
+            "at" => { "usage" => 1 },
             "oc" => {
               "may" => [
                 "gidNumber",


Reply via email to