# class Chef::Util::Windows::NetUser

wrapper around a subset of the NetUser* APIs. nothing Chef specific, but not complete enough to be its own gem, so util for now.

### Constants

DOMAIN_GROUP_RID_USERS
LOGON32_LOGON_NETWORK
LOGON32_PROVIDER_DEFAULT
LogonUser
SIZEOF_USER_INFO_3
UF_ACCOUNTDISABLE
UF_DONT_EXPIRE_PASSWD
UF_NORMAL_ACCOUNT
UF_PASSWD_CANT_CHANGE
UF_SCRIPT
USER_INFO_3

  OC-8391 Changing [:password, nil], to [:password, “”], if :password is set to nil, windows user creation api ignores the password policy applied thus initializing it with empty string value.

USER_INFO_3_TEMPLATE

### Public Class Methods

new(username) click to toggle source

    # File lib/chef/util/windows/net_user.rb, line 117
    def initialize(username)
      @username = username
      @name = multi_to_wide(username)
    end

### Public Instance Methods

add(args) click to toggle source

    # File lib/chef/util/windows/net_user.rb, line 151
    def add(args)
      user = user_info_3(args)
      buffer = user_info_3_pack(user)

      rc = NetUserAdd.call(nil, 3, buffer, rc)
      if rc != NERR_Success
        raise ArgumentError, get_last_error(rc)
      end

      #usri3_primary_group_id:
      #"When you call the NetUserAdd function, this member must be DOMAIN_GROUP_RID_USERS"
      NetLocalGroupAddMembers(nil, multi_to_wide("Users"), 3, buffer[0,PTR_SIZE], 1)
    end

check_enabled() click to toggle source

    # File lib/chef/util/windows/net_user.rb, line 208
    def check_enabled
      (get_info()[:flags] & UF_ACCOUNTDISABLE) != 0
    end

delete() click to toggle source

    # File lib/chef/util/windows/net_user.rb, line 181
    def delete
      rc = NetUserDel.call(nil, @name)
      if rc != NERR_Success
        raise ArgumentError, get_last_error(rc)
      end
    end

disable_account() click to toggle source

    # File lib/chef/util/windows/net_user.rb, line 188
    def disable_account
      user_modify do |user|
        user[:flags] |= UF_ACCOUNTDISABLE
        #This does not set the password to nil. It (for some reason) means to ignore updating the field.
        #See similar behavior for the logon_hours field documented at
        #http://msdn.microsoft.com/en-us/library/windows/desktop/aa371338%28v=vs.85%29.aspx
        user[:password] = nil
      end
    end

enable_account() click to toggle source

    # File lib/chef/util/windows/net_user.rb, line 198
    def enable_account
      user_modify do |user|
        user[:flags] &= ~UF_ACCOUNTDISABLE
        #This does not set the password to nil. It (for some reason) means to ignore updating the field.
        #See similar behavior for the logon_hours field documented at
        #http://msdn.microsoft.com/en-us/library/windows/desktop/aa371338%28v=vs.85%29.aspx
        user[:password] = nil
      end
    end

get_info() click to toggle source

    # File lib/chef/util/windows/net_user.rb, line 136
    def get_info
      ptr  = 0.chr * PTR_SIZE
      rc = NetUserGetInfo.call(nil, @name, 3, ptr)

      if rc != NERR_Success
        raise ArgumentError, get_last_error(rc)
      end

      ptr = ptr.unpack('L')[0]
      buffer = 0.chr * SIZEOF_USER_INFO_3
      memcpy(buffer, ptr, buffer.size)
      NetApiBufferFree(ptr)
      user_info_3_unpack(buffer)
    end

update(args) click to toggle source

    # File lib/chef/util/windows/net_user.rb, line 173
    def update(args)
      user_modify do |user|
        args.each do |key,val|
          user[key] = val
        end
      end
    end

user_modify(&proc) click to toggle source

    # File lib/chef/util/windows/net_user.rb, line 165
    def user_modify(&proc)
      user = get_info
      user[:last_logon] = user[:units_per_week] = 0 #ignored as per USER_INFO_3 doc
      user[:logon_hours] = nil #PBYTE field; \0 == no changes
      proc.call(user)
      set_info(user)
    end

validate_credentials(passwd) click to toggle source

XXX for an extra painful alternative, see: support.microsoft.com/kb/180548

    # File lib/chef/util/windows/net_user.rb, line 125
    def validate_credentials(passwd)
      token = 0.chr * PTR_SIZE
      res = LogonUser.call(@username, nil, passwd,
                           LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, token)
      if res == 0
        return false
      end
      ::Windows::Handle::CloseHandle.call(token.unpack('L')[0])
      return true
    end