summaryrefslogtreecommitdiffstats
path: root/source3/lib/netapi
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 17:47:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 17:47:29 +0000
commit4f5791ebd03eaec1c7da0865a383175b05102712 (patch)
tree8ce7b00f7a76baa386372422adebbe64510812d4 /source3/lib/netapi
parentInitial commit. (diff)
downloadsamba-upstream.tar.xz
samba-upstream.zip
Adding upstream version 2:4.17.12+dfsg.upstream/2%4.17.12+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source3/lib/netapi')
-rw-r--r--source3/lib/netapi/Doxyfile1362
-rw-r--r--source3/lib/netapi/cm.c284
-rw-r--r--source3/lib/netapi/examples/common.c249
-rw-r--r--source3/lib/netapi/examples/common.h18
-rw-r--r--source3/lib/netapi/examples/dsgetdc/dsgetdc.c101
-rw-r--r--source3/lib/netapi/examples/file/file_close.c83
-rw-r--r--source3/lib/netapi/examples/file/file_enum.c146
-rw-r--r--source3/lib/netapi/examples/file/file_getinfo.c112
-rw-r--r--source3/lib/netapi/examples/getdc/getdc.c86
-rw-r--r--source3/lib/netapi/examples/group/group_add.c90
-rw-r--r--source3/lib/netapi/examples/group/group_adduser.c91
-rw-r--r--source3/lib/netapi/examples/group/group_del.c82
-rw-r--r--source3/lib/netapi/examples/group/group_deluser.c91
-rw-r--r--source3/lib/netapi/examples/group/group_enum.c153
-rw-r--r--source3/lib/netapi/examples/group/group_getinfo.c127
-rw-r--r--source3/lib/netapi/examples/group/group_getusers.c132
-rw-r--r--source3/lib/netapi/examples/group/group_setinfo.c142
-rw-r--r--source3/lib/netapi/examples/group/group_setusers.c142
-rw-r--r--source3/lib/netapi/examples/join/djoin.c166
-rw-r--r--source3/lib/netapi/examples/join/getjoinableous.c110
-rw-r--r--source3/lib/netapi/examples/join/getjoininformation.c105
-rw-r--r--source3/lib/netapi/examples/join/netdomjoin.c104
-rw-r--r--source3/lib/netapi/examples/join/provision_computer_account.c122
-rw-r--r--source3/lib/netapi/examples/join/rename_machine.c101
-rw-r--r--source3/lib/netapi/examples/join/request_offline_domain_join.c97
-rw-r--r--source3/lib/netapi/examples/localgroup/localgroup_add.c106
-rw-r--r--source3/lib/netapi/examples/localgroup/localgroup_addmembers.c141
-rw-r--r--source3/lib/netapi/examples/localgroup/localgroup_del.c83
-rw-r--r--source3/lib/netapi/examples/localgroup/localgroup_delmembers.c141
-rw-r--r--source3/lib/netapi/examples/localgroup/localgroup_enum.c126
-rw-r--r--source3/lib/netapi/examples/localgroup/localgroup_getinfo.c112
-rw-r--r--source3/lib/netapi/examples/localgroup/localgroup_getmembers.c165
-rw-r--r--source3/lib/netapi/examples/localgroup/localgroup_setinfo.c128
-rw-r--r--source3/lib/netapi/examples/localgroup/localgroup_setmembers.c146
-rw-r--r--source3/lib/netapi/examples/netdomjoin-gui/logo-small.pngbin0 -> 4485 bytes
-rw-r--r--source3/lib/netapi/examples/netdomjoin-gui/logo.pngbin0 -> 9329 bytes
-rw-r--r--source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c1888
-rwxr-xr-xsource3/lib/netapi/examples/netdomjoin-gui/samba.icobin0 -> 1406 bytes
-rw-r--r--source3/lib/netapi/examples/netlogon/netlogon_control.c143
-rw-r--r--source3/lib/netapi/examples/netlogon/netlogon_control2.c147
-rw-r--r--source3/lib/netapi/examples/netlogon/nltest.c677
-rw-r--r--source3/lib/netapi/examples/server/remote_tod.c83
-rw-r--r--source3/lib/netapi/examples/server/server_getinfo.c136
-rw-r--r--source3/lib/netapi/examples/share/share_add.c105
-rw-r--r--source3/lib/netapi/examples/share/share_del.c85
-rw-r--r--source3/lib/netapi/examples/share/share_enum.c142
-rw-r--r--source3/lib/netapi/examples/share/share_getinfo.c152
-rw-r--r--source3/lib/netapi/examples/share/share_setinfo.c105
-rw-r--r--source3/lib/netapi/examples/shutdown/shutdown_abort.c76
-rw-r--r--source3/lib/netapi/examples/shutdown/shutdown_init.c94
-rw-r--r--source3/lib/netapi/examples/user/user_add.c103
-rw-r--r--source3/lib/netapi/examples/user/user_chgpwd.c99
-rw-r--r--source3/lib/netapi/examples/user/user_del.c82
-rw-r--r--source3/lib/netapi/examples/user/user_dispinfo.c100
-rw-r--r--source3/lib/netapi/examples/user/user_enum.c157
-rw-r--r--source3/lib/netapi/examples/user/user_getgroups.c133
-rw-r--r--source3/lib/netapi/examples/user/user_getinfo.c293
-rw-r--r--source3/lib/netapi/examples/user/user_getlocalgroups.c122
-rw-r--r--source3/lib/netapi/examples/user/user_modalsget.c131
-rw-r--r--source3/lib/netapi/examples/user/user_modalsset.c132
-rw-r--r--source3/lib/netapi/examples/user/user_setgroups.c144
-rw-r--r--source3/lib/netapi/examples/user/user_setinfo.c200
-rw-r--r--source3/lib/netapi/examples/wscript_build72
-rw-r--r--source3/lib/netapi/file.c283
-rw-r--r--source3/lib/netapi/getdc.c212
-rw-r--r--source3/lib/netapi/group.c1848
-rw-r--r--source3/lib/netapi/joindomain.c943
-rw-r--r--source3/lib/netapi/libnetapi.c2952
-rw-r--r--source3/lib/netapi/libnetapi.h506
-rw-r--r--source3/lib/netapi/localgroup.c1376
-rw-r--r--source3/lib/netapi/netapi.c507
-rw-r--r--source3/lib/netapi/netapi.h2735
-rw-r--r--source3/lib/netapi/netapi_net.h24
-rw-r--r--source3/lib/netapi/netapi_private.h113
-rw-r--r--source3/lib/netapi/netlogon.c248
-rw-r--r--source3/lib/netapi/samr.c346
-rw-r--r--source3/lib/netapi/serverinfo.c701
-rw-r--r--source3/lib/netapi/share.c573
-rw-r--r--source3/lib/netapi/shutdown.c110
-rw-r--r--source3/lib/netapi/sid.c71
-rw-r--r--source3/lib/netapi/tests/common.c116
-rw-r--r--source3/lib/netapi/tests/common.h67
-rw-r--r--source3/lib/netapi/tests/netapitest.c112
-rw-r--r--source3/lib/netapi/tests/netdisplay.c150
-rw-r--r--source3/lib/netapi/tests/netfile.c145
-rw-r--r--source3/lib/netapi/tests/netgroup.c503
-rw-r--r--source3/lib/netapi/tests/netlocalgroup.c226
-rw-r--r--source3/lib/netapi/tests/netserver.c61
-rw-r--r--source3/lib/netapi/tests/netshare.c250
-rw-r--r--source3/lib/netapi/tests/netuser.c462
-rw-r--r--source3/lib/netapi/tests/netwksta.c62
-rw-r--r--source3/lib/netapi/tests/wscript_build6
-rw-r--r--source3/lib/netapi/user.c3638
-rw-r--r--source3/lib/netapi/wkstainfo.c154
94 files changed, 30545 insertions, 0 deletions
diff --git a/source3/lib/netapi/Doxyfile b/source3/lib/netapi/Doxyfile
new file mode 100644
index 0000000..44bf78b
--- /dev/null
+++ b/source3/lib/netapi/Doxyfile
@@ -0,0 +1,1362 @@
+# Doxyfile 1.5.5
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = Samba
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 3.2.0pre3
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = dox
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
+# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
+# and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH = $(PWD)/
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = NO
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = NO
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = netapi.h
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS = *.c \
+ *.h \
+ *.idl
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = include/includes.h \
+ include/proto.h \
+ libnetapi.c \
+ libnetapi.h \
+ netapi.c
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = examples
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = YES
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 1
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = .
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 3
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = YES
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = NO
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is enabled by default, which results in a transparent
+# background. Warning: Depending on the platform used, enabling this option
+# may lead to badly anti-aliased labels on the edges of a graph (i.e. they
+# become hard to read).
+
+DOT_TRANSPARENT = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c
new file mode 100644
index 0000000..c54f955
--- /dev/null
+++ b/source3/lib/netapi/cm.c
@@ -0,0 +1,284 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Support
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "libsmb/libsmb.h"
+#include "rpc_client/cli_pipe.h"
+#include "../libcli/smb/smbXcli_base.h"
+
+/********************************************************************
+********************************************************************/
+
+struct client_ipc_connection {
+ struct client_ipc_connection *prev, *next;
+ struct cli_state *cli;
+ struct client_pipe_connection *pipe_connections;
+};
+
+struct client_pipe_connection {
+ struct client_pipe_connection *prev, *next;
+ struct rpc_pipe_client *pipe;
+};
+
+/********************************************************************
+********************************************************************/
+
+static struct client_ipc_connection *ipc_cm_find(
+ struct libnetapi_private_ctx *priv_ctx, const char *server_name)
+{
+ struct client_ipc_connection *p;
+
+ for (p = priv_ctx->ipc_connections; p; p = p->next) {
+ const char *remote_name = smbXcli_conn_remote_name(p->cli->conn);
+
+ if (strequal(remote_name, server_name)) {
+ return p;
+ }
+ }
+
+ return NULL;
+}
+
+/********************************************************************
+********************************************************************/
+
+static WERROR libnetapi_open_ipc_connection(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ struct client_ipc_connection **pp)
+{
+ struct libnetapi_private_ctx *priv_ctx;
+ struct cli_state *cli_ipc = NULL;
+ struct client_ipc_connection *p;
+ NTSTATUS status;
+ const char *username = NULL;
+ const char *password = NULL;
+ NET_API_STATUS rc;
+ enum credentials_use_kerberos krb5_state;
+
+ if (!ctx || !pp || !server_name) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ priv_ctx = (struct libnetapi_private_ctx *)ctx->private_data;
+
+ p = ipc_cm_find(priv_ctx, server_name);
+ if (p) {
+ *pp = p;
+ return WERR_OK;
+ }
+
+ rc = libnetapi_get_username(ctx, &username);
+ if (rc != 0) {
+ return WERR_INTERNAL_ERROR;
+ }
+
+ rc = libnetapi_get_password(ctx, &password);
+ if (rc != 0) {
+ return WERR_INTERNAL_ERROR;
+ }
+
+ if (password == NULL) {
+ cli_credentials_set_cmdline_callbacks(ctx->creds);
+ }
+
+ krb5_state = cli_credentials_get_kerberos_state(ctx->creds);
+
+ if (username != NULL && username[0] != '\0' &&
+ password != NULL && password[0] != '\0' &&
+ krb5_state == CRED_USE_KERBEROS_REQUIRED) {
+ cli_credentials_set_kerberos_state(ctx->creds,
+ CRED_USE_KERBEROS_DESIRED,
+ CRED_SPECIFIED);
+ }
+
+ status = cli_cm_open(ctx, NULL,
+ server_name, "IPC$",
+ ctx->creds,
+ NULL, 0, 0x20, &cli_ipc);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_ipc = NULL;
+ }
+
+ if (!cli_ipc) {
+ libnetapi_set_error_string(ctx,
+ "Failed to connect to IPC$ share on %s", server_name);
+ return WERR_CAN_NOT_COMPLETE;
+ }
+
+ p = talloc_zero(ctx, struct client_ipc_connection);
+ if (p == NULL) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ p->cli = cli_ipc;
+ DLIST_ADD(priv_ctx->ipc_connections, p);
+
+ *pp = p;
+
+ return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR libnetapi_shutdown_cm(struct libnetapi_ctx *ctx)
+{
+ struct libnetapi_private_ctx *priv_ctx =
+ (struct libnetapi_private_ctx *)ctx->private_data;
+ struct client_ipc_connection *p;
+
+ for (p = priv_ctx->ipc_connections; p; p = p->next) {
+ cli_shutdown(p->cli);
+ }
+
+ return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+static NTSTATUS pipe_cm_find(struct client_ipc_connection *ipc,
+ const struct ndr_interface_table *table,
+ struct rpc_pipe_client **presult)
+{
+ struct client_pipe_connection *p;
+
+ for (p = ipc->pipe_connections; p; p = p->next) {
+ const char *ipc_remote_name;
+
+ if (!rpccli_is_connected(p->pipe)) {
+ return NT_STATUS_PIPE_EMPTY;
+ }
+
+ ipc_remote_name = smbXcli_conn_remote_name(ipc->cli->conn);
+
+ if (strequal(ipc_remote_name, p->pipe->desthost)
+ && ndr_syntax_id_equal(&p->pipe->abstract_syntax,
+ &table->syntax_id)) {
+ *presult = p->pipe;
+ return NT_STATUS_OK;
+ }
+ }
+
+ return NT_STATUS_PIPE_NOT_AVAILABLE;
+}
+
+/********************************************************************
+********************************************************************/
+
+static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx,
+ struct client_ipc_connection *ipc,
+ const struct ndr_interface_table *table,
+ struct rpc_pipe_client **presult)
+{
+ struct client_pipe_connection *p;
+ NTSTATUS status;
+
+ p = talloc_zero_array(mem_ctx, struct client_pipe_connection, 1);
+ if (!p) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = cli_rpc_pipe_open_noauth(ipc->cli, table, &p->pipe);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(p);
+ return status;
+ }
+
+ DLIST_ADD(ipc->pipe_connections, p);
+
+ *presult = p->pipe;
+ return NT_STATUS_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+static NTSTATUS pipe_cm_open(TALLOC_CTX *ctx,
+ struct client_ipc_connection *ipc,
+ const struct ndr_interface_table *table,
+ struct rpc_pipe_client **presult)
+{
+ if (NT_STATUS_IS_OK(pipe_cm_find(ipc, table, presult))) {
+ return NT_STATUS_OK;
+ }
+
+ return pipe_cm_connect(ctx, ipc, table, presult);
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const struct ndr_interface_table *table,
+ struct rpc_pipe_client **presult)
+{
+ struct rpc_pipe_client *result = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ struct client_ipc_connection *ipc = NULL;
+
+ if (!presult) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ werr = libnetapi_open_ipc_connection(ctx, server_name, &ipc);
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ status = pipe_cm_open(ctx, ipc, table, &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s",
+ table->name,
+ get_friendly_nt_error_msg(status));
+ return WERR_NERR_DESTNOTFOUND;
+ }
+
+ *presult = result;
+
+ return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR libnetapi_get_binding_handle(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const struct ndr_interface_table *table,
+ struct dcerpc_binding_handle **binding_handle)
+{
+ struct rpc_pipe_client *pipe_cli;
+ WERROR result;
+
+ *binding_handle = NULL;
+
+ result = libnetapi_open_pipe(ctx, server_name, table, &pipe_cli);
+ if (!W_ERROR_IS_OK(result)) {
+ return result;
+ }
+
+ *binding_handle = pipe_cli->binding_handle;
+
+ return WERR_OK;
+}
diff --git a/source3/lib/netapi/examples/common.c b/source3/lib/netapi/examples/common.c
new file mode 100644
index 0000000..72d7150
--- /dev/null
+++ b/source3/lib/netapi/examples/common.c
@@ -0,0 +1,249 @@
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include <popt.h>
+#include <netapi.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <iconv.h>
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
+#include "common.h"
+
+void popt_common_callback(poptContext con,
+ enum poptCallbackReason reason,
+ const struct poptOption *opt,
+ const char *arg, const void *data)
+{
+ struct libnetapi_ctx *ctx = NULL;
+
+ libnetapi_getctx(&ctx);
+
+ if (reason == POPT_CALLBACK_REASON_PRE) {
+ }
+
+ if (reason == POPT_CALLBACK_REASON_POST) {
+ }
+
+ if (!opt) {
+ return;
+ }
+ switch (opt->val) {
+ case 'U': {
+ char *puser = strdup(arg);
+ char *p = NULL;
+
+ if ((p = strchr(puser,'%'))) {
+ size_t len;
+ *p = 0;
+ libnetapi_set_username(ctx, puser);
+ libnetapi_set_password(ctx, p+1);
+ len = strlen(p+1);
+ memset(strchr(arg,'%')+1,'X',len);
+ } else {
+ libnetapi_set_username(ctx, puser);
+ }
+ free(puser);
+ break;
+ }
+ case 'd':
+ libnetapi_set_debuglevel(ctx, arg);
+ break;
+ case 'p':
+ libnetapi_set_password(ctx, arg);
+ break;
+ case 'k':
+ libnetapi_set_use_kerberos(ctx);
+ break;
+ }
+}
+
+struct poptOption popt_common_netapi_examples[] = {
+ {
+ .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
+ .arg = (void *)popt_common_callback,
+ },
+ {
+ .longName = "user",
+ .shortName = 'U',
+ .argInfo = POPT_ARG_STRING,
+ .val = 'U',
+ .descrip = "Username used for connection",
+ .argDescrip = "USERNAME",
+ },
+ {
+ .longName = "password",
+ .shortName = 'p',
+ .argInfo = POPT_ARG_STRING,
+ .val = 'p',
+ .descrip = "Password used for connection",
+ .argDescrip = "PASSWORD",
+ },
+ {
+ .longName = "debuglevel",
+ .shortName = 'd',
+ .argInfo = POPT_ARG_STRING,
+ .val = 'd',
+ .descrip = "Debuglevel",
+ .argDescrip = "DEBUGLEVEL",
+ },
+ {
+ .longName = "kerberos",
+ .shortName = 'k',
+ .argInfo = POPT_ARG_NONE,
+ .val = 'k',
+ .descrip = "Use Kerberos",
+ },
+ POPT_TABLEEND
+};
+
+char *netapi_read_file(const char *filename, uint32_t *psize)
+{
+ int fd;
+ FILE *file = NULL;
+ char *p = NULL;
+ size_t size = 0;
+ size_t chunk = 1024;
+ size_t maxsize = SIZE_MAX;
+ int err;
+
+ fd = open(filename, O_RDONLY);
+ if (fd == -1) {
+ goto fail;
+ }
+
+ file = fdopen(fd, "r");
+ if (file == NULL) {
+ goto fail;
+ }
+
+ while (size < maxsize) {
+ char *tmp = NULL;
+ size_t newbufsize;
+ size_t nread;
+
+ chunk = MIN(chunk, (maxsize - size));
+
+ newbufsize = size + (chunk+1); /* chunk+1 can't overflow */
+ if (newbufsize < size) {
+ goto fail; /* overflow */
+ }
+
+ tmp = realloc(p, sizeof(char) * newbufsize);
+ if (tmp == NULL) {
+ free(p);
+ p = NULL;
+ goto fail;
+ }
+ p = tmp;
+
+ nread = fread(p+size, 1, chunk, file);
+ size += nread;
+
+ if (nread != chunk) {
+ break;
+ }
+ }
+
+ err = ferror(file);
+ if (err != 0) {
+ free(p);
+ goto fail;
+ }
+
+ p[size] = '\0';
+
+ if (psize != NULL) {
+ *psize = size;
+ }
+ fail:
+ if (file != NULL) {
+ fclose(file);
+ }
+ if (fd >= 0) {
+ close(fd);
+ }
+
+ return p;
+}
+
+int netapi_save_file(const char *fname, void *ppacket, size_t length)
+{
+ int fd;
+ fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (fd == -1) {
+ perror(fname);
+ return -1;
+ }
+ if (write(fd, ppacket, length) != length) {
+ fprintf(stderr,"Failed to write %s\n", fname);
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ return 0;
+}
+
+int netapi_save_file_ucs2(const char *fname, const char *str)
+{
+ char *str_p = NULL;
+ char *ucs2_str = NULL;
+ size_t str_len = 0;
+ size_t ucs2_str_len = 0;
+ iconv_t cd;
+ int ret;
+ char *start;
+ size_t start_len;
+ char *p;
+
+ str_len = strlen(str) + 1;
+ ucs2_str_len = 2 * str_len; /* room for ucs2 */
+ ucs2_str_len += 2;
+
+ ucs2_str = calloc(ucs2_str_len, sizeof(char));
+ if (ucs2_str == NULL) {
+ return -1;
+ }
+ p = ucs2_str; /* store for free */
+
+ ucs2_str[0] = 0xff;
+ ucs2_str[1] = 0xfe;
+
+ start = ucs2_str;
+ start_len = ucs2_str_len;
+
+ ucs2_str += 2;
+ ucs2_str_len -= 2;
+
+ cd = iconv_open("UTF-16LE", "ASCII");
+ if (cd == (iconv_t)-1) {
+ free(p);
+ return -1;
+ }
+
+ str_p = (void *)((uintptr_t)str);
+
+ ret = iconv(cd,
+ &str_p,
+ &str_len,
+ &ucs2_str,
+ &ucs2_str_len);
+ if (ret == -1) {
+ free(p);
+ return -1;
+ }
+ iconv_close(cd);
+
+ ret = netapi_save_file(fname, start, start_len);
+ free(p);
+
+ return ret;
+}
diff --git a/source3/lib/netapi/examples/common.h b/source3/lib/netapi/examples/common.h
new file mode 100644
index 0000000..df7f176
--- /dev/null
+++ b/source3/lib/netapi/examples/common.h
@@ -0,0 +1,18 @@
+#include <popt.h>
+
+void popt_common_callback(poptContext con,
+ enum poptCallbackReason reason,
+ const struct poptOption *opt,
+ const char *arg, const void *data);
+
+extern struct poptOption popt_common_netapi_examples[];
+
+#ifndef POPT_TABLEEND
+#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
+#endif
+
+#define POPT_COMMON_LIBNETAPI_EXAMPLES { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_netapi_examples, 0, "Common samba netapi example options:", NULL },
+
+char *netapi_read_file(const char *filename, uint32_t *psize);
+int netapi_save_file(const char *fname, void *ppacket, size_t length);
+int netapi_save_file_ucs2(const char *fname, const char *str);
diff --git a/source3/lib/netapi/examples/dsgetdc/dsgetdc.c b/source3/lib/netapi/examples/dsgetdc/dsgetdc.c
new file mode 100644
index 0000000..6265e66
--- /dev/null
+++ b/source3/lib/netapi/examples/dsgetdc/dsgetdc.c
@@ -0,0 +1,101 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * DsGetDcName query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+
+ const char *hostname = NULL;
+ const char *domain = NULL;
+ uint32_t flags = 0;
+ struct DOMAIN_CONTROLLER_INFO *info = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ { "flags", 0, POPT_ARG_INT, NULL, 'f', "Query flags", "FLAGS" },
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("dsgetdc", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname domainname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case 'f':
+ sscanf(poptGetOptArg(pc), "%x", &flags);
+ }
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ domain = poptGetArg(pc);
+
+ /* DsGetDcName */
+
+ status = DsGetDcName(hostname, domain, NULL, NULL, flags, &info);
+ if (status != 0) {
+ printf("DsGetDcName failed with: %s\n",
+ libnetapi_errstr(status));
+ return status;
+ }
+
+ printf("DC Name:\t\t%s\n", info->domain_controller_name);
+ printf("DC Address:\t\t%s\n", info->domain_controller_address);
+ printf("DC Address Type:\t%d\n", info->domain_controller_address_type);
+ printf("Domain Name:\t\t%s\n", info->domain_name);
+ printf("DNS Forest Name:\t%s\n", info->dns_forest_name);
+ printf("DC flags:\t\t0x%08x\n", info->flags);
+ printf("DC Sitename:\t\t%s\n", info->dc_site_name);
+ printf("Client Sitename:\t%s\n", info->client_site_name);
+
+ out:
+ NetApiBufferFree(info);
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/file/file_close.c b/source3/lib/netapi/examples/file/file_close.c
new file mode 100644
index 0000000..759173a
--- /dev/null
+++ b/source3/lib/netapi/examples/file/file_close.c
@@ -0,0 +1,83 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetFileClose query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint32_t fileid = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("file_close", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname fileid");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ fileid = atoi(poptGetArg(pc));
+
+ /* NetFileClose */
+
+ status = NetFileClose(hostname, fileid);
+ if (status != 0) {
+ printf("NetFileClose failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/file/file_enum.c b/source3/lib/netapi/examples/file/file_enum.c
new file mode 100644
index 0000000..5fbb285
--- /dev/null
+++ b/source3/lib/netapi/examples/file/file_enum.c
@@ -0,0 +1,146 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetFileEnum query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *basepath = NULL;
+ const char *username = NULL;
+ uint32_t level = 3;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int i;
+
+ struct FILE_INFO_2 *i2 = NULL;
+ struct FILE_INFO_3 *i3 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("file_enum", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname basepath username level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ basepath = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetFileEnum */
+
+ do {
+
+ status = NetFileEnum(hostname,
+ basepath,
+ username,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ printf("total entries: %d\n", total_entries);
+ switch (level) {
+ case 2:
+ i2 = (struct FILE_INFO_2 *)buffer;
+ break;
+ case 3:
+ i3 = (struct FILE_INFO_3 *)buffer;
+ break;
+ default:
+ break;
+ }
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 2:
+ printf("file_id: %d\n", i2->fi2_id);
+ i2++;
+ break;
+ case 3:
+ printf("file_id: %d\n", i3->fi3_id);
+ printf("permissions: %d\n", i3->fi3_permissions);
+ printf("num_locks: %d\n", i3->fi3_num_locks);
+ printf("pathname: %s\n", i3->fi3_pathname);
+ printf("username: %s\n", i3->fi3_username);
+ i3++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetFileEnum failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/file/file_getinfo.c b/source3/lib/netapi/examples/file/file_getinfo.c
new file mode 100644
index 0000000..9ad8305
--- /dev/null
+++ b/source3/lib/netapi/examples/file/file_getinfo.c
@@ -0,0 +1,112 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetFileGetInfo query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint32_t fileid = 0;
+ uint32_t level = 3;
+ uint8_t *buffer = NULL;
+
+ struct FILE_INFO_2 *i2 = NULL;
+ struct FILE_INFO_3 *i3 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("file_getinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname fileid");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ fileid = atoi(poptGetArg(pc));
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetFileGetInfo */
+
+ status = NetFileGetInfo(hostname,
+ fileid,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("NetFileGetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ switch (level) {
+ case 2:
+ i2 = (struct FILE_INFO_2 *)buffer;
+ printf("file_id: %d\n", i2->fi2_id);
+ break;
+ case 3:
+ i3 = (struct FILE_INFO_3 *)buffer;
+ printf("file_id: %d\n", i3->fi3_id);
+ printf("permissions: %d\n", i3->fi3_permissions);
+ printf("num_locks: %d\n", i3->fi3_num_locks);
+ printf("pathname: %s\n", i3->fi3_pathname);
+ printf("username: %s\n", i3->fi3_username);
+ break;
+ default:
+ break;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/getdc/getdc.c b/source3/lib/netapi/examples/getdc/getdc.c
new file mode 100644
index 0000000..98bb6a1
--- /dev/null
+++ b/source3/lib/netapi/examples/getdc/getdc.c
@@ -0,0 +1,86 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * GetDCName query
+ * Copyright (C) Guenther Deschner 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+
+ const char *hostname = NULL;
+ const char *domain = NULL;
+ uint8_t *buffer = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("getdc", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname domainname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ domain = poptGetArg(pc);
+
+ /* NetGetDCName */
+
+ status = NetGetDCName(hostname, domain, &buffer);
+ if (status != 0) {
+ printf("GetDcName failed with: %s\n", libnetapi_errstr(status));
+ } else {
+ printf("%s\n", (char *)buffer);
+ }
+
+ out:
+ NetApiBufferFree(buffer);
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/group/group_add.c b/source3/lib/netapi/examples/group/group_add.c
new file mode 100644
index 0000000..4da97c5
--- /dev/null
+++ b/source3/lib/netapi/examples/group/group_add.c
@@ -0,0 +1,90 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupAdd query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ struct GROUP_INFO_1 g1;
+ uint32_t parm_error = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_add", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ /* NetGroupAdd */
+
+ g1.grpi1_name = groupname;
+ g1.grpi1_comment = "Domain Group created using NetApi example code";
+
+ status = NetGroupAdd(hostname,
+ 1,
+ (uint8_t *)&g1,
+ &parm_error);
+ if (status != 0) {
+ printf("NetGroupAdd failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/group/group_adduser.c b/source3/lib/netapi/examples/group/group_adduser.c
new file mode 100644
index 0000000..253b3c5
--- /dev/null
+++ b/source3/lib/netapi/examples/group/group_adduser.c
@@ -0,0 +1,91 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupAddUser query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ const char *username = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_adduser", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname username");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ /* NetGroupAddUser */
+
+ status = NetGroupAddUser(hostname,
+ groupname,
+ username);
+ if (status != 0) {
+ printf("NetGroupAddUser failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/group/group_del.c b/source3/lib/netapi/examples/group/group_del.c
new file mode 100644
index 0000000..789e429
--- /dev/null
+++ b/source3/lib/netapi/examples/group/group_del.c
@@ -0,0 +1,82 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupDel query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_del", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ /* NetGroupDel */
+
+ status = NetGroupDel(hostname, groupname);
+ if (status != 0) {
+ printf("NetGroupDel failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/group/group_deluser.c b/source3/lib/netapi/examples/group/group_deluser.c
new file mode 100644
index 0000000..751ab5c
--- /dev/null
+++ b/source3/lib/netapi/examples/group/group_deluser.c
@@ -0,0 +1,91 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupDelUser query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ const char *username = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_deluser", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname username");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ /* NetGroupDelUser */
+
+ status = NetGroupDelUser(hostname,
+ groupname,
+ username);
+ if (status != 0) {
+ printf("NetGroupDelUser failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/group/group_enum.c b/source3/lib/netapi/examples/group/group_enum.c
new file mode 100644
index 0000000..fe2aee1
--- /dev/null
+++ b/source3/lib/netapi/examples/group/group_enum.c
@@ -0,0 +1,153 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupEnum query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int i;
+ char *sid_str = NULL;
+
+ struct GROUP_INFO_0 *info0 = NULL;
+ struct GROUP_INFO_1 *info1 = NULL;
+ struct GROUP_INFO_2 *info2 = NULL;
+ struct GROUP_INFO_3 *info3 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_enum", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetGroupEnum */
+
+ do {
+ status = NetGroupEnum(hostname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ printf("total entries: %d\n", total_entries);
+ switch (level) {
+ case 0:
+ info0 = (struct GROUP_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct GROUP_INFO_1 *)buffer;
+ break;
+ case 2:
+ info2 = (struct GROUP_INFO_2 *)buffer;
+ break;
+ case 3:
+ info3 = (struct GROUP_INFO_3 *)buffer;
+ break;
+ default:
+ break;
+ }
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ printf("#%d group: %s\n", i, info0->grpi0_name);
+ info0++;
+ break;
+ case 1:
+ printf("#%d group: %s\n", i, info1->grpi1_name);
+ printf("#%d comment: %s\n", i, info1->grpi1_comment);
+ info1++;
+ break;
+ case 2:
+ printf("#%d group: %s\n", i, info2->grpi2_name);
+ printf("#%d comment: %s\n", i, info2->grpi2_comment);
+ printf("#%d rid: %d\n", i, info2->grpi2_group_id);
+ printf("#%d attributes: 0x%08x\n", i, info2->grpi2_attributes);
+ info2++;
+ break;
+ case 3:
+ printf("#%d group: %s\n", i, info3->grpi3_name);
+ printf("#%d comment: %s\n", i, info3->grpi3_comment);
+ if (ConvertSidToStringSid(info3->grpi3_group_sid,
+ &sid_str)) {
+ printf("#%d group_sid: %s\n", i, sid_str);
+ free(sid_str);
+ }
+ printf("#%d attributes: 0x%08x\n", i, info3->grpi3_attributes);
+ info3++;
+ break;
+
+
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetGroupEnum failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/group/group_getinfo.c b/source3/lib/netapi/examples/group/group_getinfo.c
new file mode 100644
index 0000000..2e5b793
--- /dev/null
+++ b/source3/lib/netapi/examples/group/group_getinfo.c
@@ -0,0 +1,127 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupGetInfo query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 0;
+ struct GROUP_INFO_0 *g0;
+ struct GROUP_INFO_1 *g1;
+ struct GROUP_INFO_2 *g2;
+ struct GROUP_INFO_3 *g3;
+ char *sid_str = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_getinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetGroupGetInfo */
+
+ status = NetGroupGetInfo(hostname,
+ groupname,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("NetGroupGetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ switch (level) {
+ case 0:
+ g0 = (struct GROUP_INFO_0 *)buffer;
+ printf("name: %s\n", g0->grpi0_name);
+ break;
+ case 1:
+ g1 = (struct GROUP_INFO_1 *)buffer;
+ printf("name: %s\n", g1->grpi1_name);
+ printf("comment: %s\n", g1->grpi1_comment);
+ break;
+ case 2:
+ g2 = (struct GROUP_INFO_2 *)buffer;
+ printf("name: %s\n", g2->grpi2_name);
+ printf("comment: %s\n", g2->grpi2_comment);
+ printf("group_id: %d\n", g2->grpi2_group_id);
+ printf("attributes: %d\n", g2->grpi2_attributes);
+ break;
+ case 3:
+ g3 = (struct GROUP_INFO_3 *)buffer;
+ printf("name: %s\n", g3->grpi3_name);
+ printf("comment: %s\n", g3->grpi3_comment);
+ if (ConvertSidToStringSid(g3->grpi3_group_sid,
+ &sid_str)) {
+ printf("group_sid: %s\n", sid_str);
+ free(sid_str);
+ }
+ printf("attributes: %d\n", g3->grpi3_attributes);
+ break;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/group/group_getusers.c b/source3/lib/netapi/examples/group/group_getusers.c
new file mode 100644
index 0000000..72e79ec
--- /dev/null
+++ b/source3/lib/netapi/examples/group/group_getusers.c
@@ -0,0 +1,132 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupGetUsers query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int i;
+
+ struct GROUP_USERS_INFO_0 *info0 = NULL;
+ struct GROUP_USERS_INFO_1 *info1 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_getusers", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetGroupGetUsers */
+
+ do {
+ status = NetGroupGetUsers(hostname,
+ groupname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ printf("total entries: %d\n", total_entries);
+ switch (level) {
+ case 0:
+ info0 = (struct GROUP_USERS_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct GROUP_USERS_INFO_1 *)buffer;
+ break;
+ default:
+ break;
+ }
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ printf("#%d member: %s\n", i, info0->grui0_name);
+ info0++;
+ break;
+ case 1:
+ printf("#%d member: %s\n", i, info1->grui1_name);
+ printf("#%d attributes: %d\n", i, info1->grui1_attributes);
+ info1++;
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetGroupGetUsers failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/group/group_setinfo.c b/source3/lib/netapi/examples/group/group_setinfo.c
new file mode 100644
index 0000000..cd30d8b
--- /dev/null
+++ b/source3/lib/netapi/examples/group/group_setinfo.c
@@ -0,0 +1,142 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupSetInfo query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ const char *option = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 0;
+ uint32_t parm_err = 0;
+ struct GROUP_INFO_0 g0;
+ struct GROUP_INFO_1 g1;
+ struct GROUP_INFO_2 g2;
+ struct GROUP_INFO_3 g3;
+ struct GROUP_INFO_1002 g1002;
+ struct GROUP_INFO_1005 g1005;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_setinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname level option");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ level = atoi(poptGetArg(pc));
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ option = poptGetArg(pc);
+
+ /* NetGroupSetInfo */
+
+ switch (level) {
+ case 0:
+ g0.grpi0_name = option;
+ buffer = (uint8_t *)&g0;
+ break;
+ case 1:
+ g1.grpi1_name = option; /* this one will be ignored */
+ g1.grpi1_comment = option;
+ buffer = (uint8_t *)&g1;
+ break;
+ case 2:
+ g2.grpi2_name = option; /* this one will be ignored */
+ g2.grpi2_comment = option;
+ g2.grpi2_group_id = 4711; /* this one will be ignored */
+ g2.grpi2_attributes = 7;
+ buffer = (uint8_t *)&g2;
+ break;
+ case 3:
+ g3.grpi3_name = option; /* this one will be ignored */
+ g3.grpi3_comment = option;
+ g2.grpi2_attributes = 7;
+ buffer = (uint8_t *)&g3;
+ break;
+ case 1002:
+ g1002.grpi1002_comment = option;
+ buffer = (uint8_t *)&g1002;
+ break;
+ case 1005:
+ g1005.grpi1005_attributes = atoi(option);
+ buffer = (uint8_t *)&g1005;
+ break;
+ }
+
+ status = NetGroupSetInfo(hostname,
+ groupname,
+ level,
+ buffer,
+ &parm_err);
+ if (status != 0) {
+ printf("NetGroupSetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/group/group_setusers.c b/source3/lib/netapi/examples/group/group_setusers.c
new file mode 100644
index 0000000..70cf105
--- /dev/null
+++ b/source3/lib/netapi/examples/group/group_setusers.c
@@ -0,0 +1,142 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupSetUsers query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t num_entries = 0;
+ const char **names = NULL;
+ int i = 0;
+ size_t buf_size = 0;
+
+ struct GROUP_USERS_INFO_0 *g0 = NULL;
+ struct GROUP_USERS_INFO_1 *g1 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_setusers", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+
+ names = poptGetArgs(pc);
+ for (i=0; names[i] != NULL; i++) {
+ num_entries++;
+ }
+
+ switch (level) {
+ case 0:
+ buf_size = sizeof(struct GROUP_USERS_INFO_0) * num_entries;
+
+ status = NetApiBufferAllocate(buf_size, (void **)&g0);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<num_entries; i++) {
+ g0[i].grui0_name = names[i];
+ }
+
+ buffer = (uint8_t *)g0;
+ break;
+ case 1:
+ buf_size = sizeof(struct GROUP_USERS_INFO_1) * num_entries;
+
+ status = NetApiBufferAllocate(buf_size, (void **)&g1);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<num_entries; i++) {
+ g1[i].grui1_name = names[i];
+ }
+
+ buffer = (uint8_t *)g1;
+ break;
+ default:
+ break;
+ }
+
+ /* NetGroupSetUsers */
+
+ status = NetGroupSetUsers(hostname,
+ groupname,
+ level,
+ buffer,
+ num_entries);
+ if (status != 0) {
+ printf("NetGroupSetUsers failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/join/djoin.c b/source3/lib/netapi/examples/join/djoin.c
new file mode 100644
index 0000000..737f330
--- /dev/null
+++ b/source3/lib/netapi/examples/join/djoin.c
@@ -0,0 +1,166 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Offline Domain Join utility
+ * Copyright (C) Guenther Deschner 2021
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ const char *domain = NULL;
+ const char *machine_name = NULL;
+ const char *windows_path = NULL;
+ const char *dcname = NULL;
+ const char *loadfile = NULL;
+ const char *savefile = NULL;
+ const char *machine_account_ou = NULL;
+ uint32_t options = 0;
+ uint8_t *provision_bin_data = NULL;
+ uint32_t provision_bin_data_size = 0;
+ const char *provision_text_data = NULL;
+ int provision = 0;
+ int requestodj = 0;
+ int default_password = 0;
+ int print_blob = 0;
+ int localos = 0;
+ int reuse = 0;
+
+ struct libnetapi_ctx *ctx = NULL;
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ { "provision", 0, POPT_ARG_NONE, &provision, 'D', "Create computer account in AD", NULL },
+ { "dcname", 0, POPT_ARG_STRING, &dcname, 'D', "Domain Controller Name", "DCNAME" },
+ { "machine_account_ou", 0, POPT_ARG_STRING, &machine_account_ou, 'D', "LDAP DN for Machine Account OU", "MACHINE_ACCOUNT_OU" },
+ { "domain", 0, POPT_ARG_STRING, &domain, 'D', "Domain name", "DOMAIN" },
+ { "machine_name", 0, POPT_ARG_STRING, &machine_name, 'D', "Computer Account Name", "MACHINENAME" },
+ { "defpwd", 0, POPT_ARG_NONE, &default_password, 'D', "Use default password for machine account (not recommended)", "" },
+ { "printblob", 0, POPT_ARG_NONE, &print_blob, 'D', "Print base64 encoded ODJ blob (for Windows answer files)", "" },
+ { "savefile", 0, POPT_ARG_STRING, &savefile, 'D', "Save ODJ blob to file (for Windows answer files)", "FILENAME" },
+ { "reuse", 0, POPT_ARG_NONE, &reuse, 'D', "Reuse machine account", "" },
+ { "requestodj", 0, POPT_ARG_NONE, &requestodj, 'D', "Load offline join data", NULL },
+ { "loadfile", 0, POPT_ARG_STRING, &loadfile, 'D', "Load file from previous provision", "FILENAME" },
+ { "localos", 0, POPT_ARG_NONE, &localos, 'D', "Request local OS to load offline join information", "" },
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("djoin", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "[provision|requestodj]");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (provision) {
+
+ if (domain == NULL) {
+ printf("domain must be defined\n");
+ goto out;
+ }
+
+ if (machine_name == NULL) {
+ printf("machine_name must be defined\n");
+ goto out;
+ }
+
+ if (default_password) {
+ options |= NETSETUP_PROVISION_USE_DEFAULT_PASSWORD;
+ }
+
+ if (reuse) {
+ options |= NETSETUP_PROVISION_REUSE_ACCOUNT;
+ }
+
+ status = NetProvisionComputerAccount(domain,
+ machine_name,
+ machine_account_ou,
+ dcname,
+ options,
+ NULL,
+ 0,
+ &provision_text_data);
+ if (status != 0) {
+ printf("failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ if (print_blob) {
+ printf("Provision Text Data: %s\n", provision_text_data);
+ }
+
+ if (savefile != NULL) {
+ status = netapi_save_file_ucs2(savefile, provision_text_data);
+ if (status != 0) {
+ goto out;
+ }
+ }
+ }
+
+ if (requestodj) {
+
+ if (loadfile == NULL) {
+ printf("--loadfile <FILENAME> is required\n");
+ goto out;
+ }
+ provision_bin_data = (uint8_t *)netapi_read_file(loadfile,
+ &provision_bin_data_size);
+ if (provision_bin_data == NULL) {
+ printf("failed to read loadfile: %s\n", loadfile);
+ goto out;
+ }
+
+ if (localos) {
+ options |= NETSETUP_PROVISION_ONLINE_CALLER;
+ }
+
+ status = NetRequestOfflineDomainJoin(provision_bin_data,
+ provision_bin_data_size,
+ options,
+ windows_path);
+ free(provision_bin_data);
+
+ if (status != 0 && status != 0x00000a99) {
+ /* NERR_JoinPerformedMustRestart */
+ printf("failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/join/getjoinableous.c b/source3/lib/netapi/examples/join/getjoinableous.c
new file mode 100644
index 0000000..c0fba57
--- /dev/null
+++ b/source3/lib/netapi/examples/join/getjoinableous.c
@@ -0,0 +1,110 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Join Support (cmdline + netapi)
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ const char *host_name = NULL;
+ const char *domain_name = NULL;
+ const char **ous = NULL;
+ uint32_t num_ous = 0;
+ struct libnetapi_ctx *ctx = NULL;
+ int i;
+ const char *username = NULL;
+ const char *password = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ { "domain", 0, POPT_ARG_STRING, NULL, 'D', "Domain name", "DOMAIN" },
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("getjoinableous", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname domainname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case 'D':
+ domain_name = poptGetOptArg(pc);
+ break;
+ }
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ host_name = poptGetArg(pc);
+
+ /* NetGetJoinableOUs */
+
+ status = libnetapi_get_username(ctx, &username);
+ if (status != 0) {
+ printf("failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+ status = libnetapi_get_password(ctx, &password);
+ if (status != 0) {
+ printf("failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ status = NetGetJoinableOUs(host_name,
+ domain_name,
+ username,
+ password,
+ &num_ous,
+ &ous);
+ if (status != 0) {
+ printf("failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ } else {
+ printf("Successfully queried joinable ous:\n");
+ for (i=0; i<num_ous; i++) {
+ printf("ou: %s\n", ous[i]);
+ }
+ }
+
+ out:
+ NetApiBufferFree(ous);
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/join/getjoininformation.c b/source3/lib/netapi/examples/join/getjoininformation.c
new file mode 100644
index 0000000..7dac456
--- /dev/null
+++ b/source3/lib/netapi/examples/join/getjoininformation.c
@@ -0,0 +1,105 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Join Support (cmdline + netapi)
+ * Copyright (C) Guenther Deschner 2009
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "replace.h"
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ const char *host_name = NULL;
+ char *name_buffer = NULL;
+ const char *p = NULL;
+ uint16_t name_type = 0;
+ struct libnetapi_ctx *ctx = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("getjoininformation", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ host_name = poptGetArg(pc);
+
+ /* NetGetJoinInformation */
+
+ status = NetGetJoinInformation(host_name, &p, &name_type);
+ name_buffer = discard_const_p(char, p);
+ if (status != 0) {
+ printf("failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ } else {
+ printf("Successfully queried join information:\n");
+
+ switch (name_type) {
+ case NetSetupUnknownStatus:
+ printf("%s's join status unknown (name: %s)\n",
+ host_name, name_buffer);
+ break;
+ case NetSetupUnjoined:
+ printf("%s is not joined (name: %s)\n",
+ host_name, name_buffer);
+ break;
+ case NetSetupWorkgroupName:
+ printf("%s is joined to workgroup %s\n",
+ host_name, name_buffer);
+ break;
+ case NetSetupDomainName:
+ printf("%s is joined to domain %s\n",
+ host_name, name_buffer);
+ break;
+ default:
+ printf("%s is in unknown status %d (name: %s)\n",
+ host_name, name_type, name_buffer);
+ break;
+ }
+ }
+
+ out:
+ NetApiBufferFree(name_buffer);
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/join/netdomjoin.c b/source3/lib/netapi/examples/join/netdomjoin.c
new file mode 100644
index 0000000..08ce71b
--- /dev/null
+++ b/source3/lib/netapi/examples/join/netdomjoin.c
@@ -0,0 +1,104 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Join Support (cmdline + netapi)
+ * Copyright (C) Guenther Deschner 2007-2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+enum {
+ OPT_OU = 1000
+};
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ const char *host_name = NULL;
+ const char *domain_name = NULL;
+ const char *account_ou = NULL;
+ const char *account = NULL;
+ const char *password = NULL;
+ uint32_t join_flags = NETSETUP_JOIN_DOMAIN |
+ NETSETUP_ACCT_CREATE |
+ NETSETUP_DOMAIN_JOIN_IF_JOINED;
+ struct libnetapi_ctx *ctx = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ { "ou", 0, POPT_ARG_STRING, &account_ou, 'U', "Account ou", "ACCOUNT_OU" },
+ { "domain", 0, POPT_ARG_STRING, &domain_name, 'U', "Domain name (required)", "DOMAIN" },
+ { "userd", 0, POPT_ARG_STRING, &account, 'U', "Domain admin account", "USERNAME" },
+ { "passwordd", 0, POPT_ARG_STRING, &password, 'U', "Domain admin password", "PASSWORD" },
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("netdomjoin", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ host_name = poptGetArg(pc);
+
+ if (!domain_name) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+
+ /* NetJoinDomain */
+
+ status = NetJoinDomain(host_name,
+ domain_name,
+ account_ou,
+ account,
+ password,
+ join_flags);
+ if (status != 0) {
+ const char *errstr = NULL;
+ errstr = libnetapi_get_error_string(ctx, status);
+ printf("Join failed with: %s\n", errstr);
+ } else {
+ printf("Successfully joined\n");
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/join/provision_computer_account.c b/source3/lib/netapi/examples/join/provision_computer_account.c
new file mode 100644
index 0000000..cc2dde5
--- /dev/null
+++ b/source3/lib/netapi/examples/join/provision_computer_account.c
@@ -0,0 +1,122 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetProvisionComputerAccount query
+ * Copyright (C) Guenther Deschner 2021
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ const char *domain = NULL;
+ const char *machine_name = NULL;
+ const char *machine_account_ou = NULL;
+ const char *dcname = NULL;
+ uint32_t options = 0;
+ const char *provision_text_data = NULL;
+ int default_password = 0;
+ int print_blob = 0;
+ const char *savefile = NULL;
+ int reuse = 0;
+
+ struct libnetapi_ctx *ctx = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ { "dcname", 0, POPT_ARG_STRING, &dcname, 'D', "Domain Controller Name", "DCNAME" },
+ { "machine_account_ou", 0, POPT_ARG_STRING, &machine_account_ou, 'D', "LDAP DN for Machine Account OU", "MACHINE_ACCOUNT_OU" },
+ { "defpwd", 0, POPT_ARG_NONE, &default_password, 'D', "Use default password for machine account (not recommended)", "" },
+ { "printblob", 0, POPT_ARG_NONE, &print_blob, 'D', "Print base64 encoded ODJ blob (for Windows answer files)", "" },
+ { "savefile", 0, POPT_ARG_STRING, &savefile, 'D', "Save ODJ blob to file (for Windows answer files)", "FILENAME" },
+ { "reuse", 0, POPT_ARG_NONE, &reuse, 'D', "Reuse machine account", "" },
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("provision_computer_account", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "domain machine_name");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ domain = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ machine_name = poptGetArg(pc);
+
+ if (default_password) {
+ options |= NETSETUP_PROVISION_USE_DEFAULT_PASSWORD;
+ }
+ if (reuse) {
+ options |= NETSETUP_PROVISION_REUSE_ACCOUNT;
+ }
+
+ /* NetProvisionComputerAccount */
+
+ status = NetProvisionComputerAccount(domain,
+ machine_name,
+ machine_account_ou,
+ dcname,
+ options,
+ NULL,
+ 0,
+ &provision_text_data);
+ if (status != 0) {
+ printf("failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ if (print_blob) {
+ printf("Provision data: %s\n", provision_text_data);
+ }
+
+ if (savefile != NULL) {
+ status = netapi_save_file_ucs2(savefile, provision_text_data);
+ if (status != 0) {
+ goto out;
+ }
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/join/rename_machine.c b/source3/lib/netapi/examples/join/rename_machine.c
new file mode 100644
index 0000000..7be6dc2
--- /dev/null
+++ b/source3/lib/netapi/examples/join/rename_machine.c
@@ -0,0 +1,101 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetRenameMachineInDomain query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ const char *host_name = NULL;
+ const char *new_machine_name = NULL;
+ uint32_t rename_opt = 0;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *username = NULL;
+ const char *password = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("rename_machine", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname newmachinename");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ host_name = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ new_machine_name = poptGetArg(pc);
+
+ /* NetRenameMachineInDomain */
+
+ status = libnetapi_get_username(ctx, &username);
+ if (status != 0) {
+ printf("failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+ status = libnetapi_get_password(ctx, &password);
+ if (status != 0) {
+ printf("failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ status = NetRenameMachineInDomain(host_name,
+ new_machine_name,
+ username,
+ password,
+ rename_opt);
+ if (status != 0) {
+ printf("failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/join/request_offline_domain_join.c b/source3/lib/netapi/examples/join/request_offline_domain_join.c
new file mode 100644
index 0000000..96bbe0b
--- /dev/null
+++ b/source3/lib/netapi/examples/join/request_offline_domain_join.c
@@ -0,0 +1,97 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetRequestOfflineDomainJoin
+ * Copyright (C) Guenther Deschner 2021
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ const char *windows_path = NULL;
+ uint32_t options = 0;
+ uint8_t *provision_bin_data = NULL;
+ uint32_t provision_bin_data_size = 0;
+ const char *loadfile = NULL;
+ struct libnetapi_ctx *ctx = NULL;
+ int localos = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ { "loadfile", 0, POPT_ARG_STRING, &loadfile, 'D', "Load file from previous provision", "FILENAME" },
+ { "localos", 0, POPT_ARG_NONE, &localos, 'D', "Request local OS to load offline join information", "" },
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("request_offline_domain_join", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (loadfile == NULL) {
+ printf("--loadfile <FILENAME> is required\n");
+ goto out;
+ }
+ provision_bin_data = (uint8_t *)netapi_read_file(loadfile,
+ &provision_bin_data_size);
+ if (provision_bin_data == NULL) {
+ printf("failed to read loadfile: %s\n", loadfile);
+ goto out;
+ }
+
+ if (localos) {
+ options |= NETSETUP_PROVISION_ONLINE_CALLER;
+ }
+
+ /* NetRequestOfflineDomainJoin */
+
+ status = NetRequestOfflineDomainJoin(provision_bin_data,
+ provision_bin_data_size,
+ options,
+ windows_path);
+ free(provision_bin_data);
+ if (status != 0 && status != 0x00000a99) {
+ /* NERR_JoinPerformedMustRestart */
+ printf("failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/localgroup/localgroup_add.c b/source3/lib/netapi/examples/localgroup/localgroup_add.c
new file mode 100644
index 0000000..7f23c99
--- /dev/null
+++ b/source3/lib/netapi/examples/localgroup/localgroup_add.c
@@ -0,0 +1,106 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupAdd query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ const char *comment = NULL;
+ struct LOCALGROUP_INFO_0 g0;
+ struct LOCALGROUP_INFO_1 g1;
+ uint32_t parm_error = 0;
+ uint8_t *buf = NULL;
+ uint32_t level = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_add", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname comment");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ comment = poptGetArg(pc);
+ }
+
+ /* NetLocalGroupAdd */
+
+ if (comment) {
+ level = 1;
+ g1.lgrpi1_name = groupname;
+ g1.lgrpi1_comment = comment;
+ buf = (uint8_t *)&g1;
+ } else {
+ level = 0;
+ g0.lgrpi0_name = groupname;
+ buf = (uint8_t *)&g0;
+ }
+
+ status = NetLocalGroupAdd(hostname,
+ level,
+ buf,
+ &parm_error);
+ if (status != 0) {
+ printf("NetLocalGroupAdd failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/localgroup/localgroup_addmembers.c b/source3/lib/netapi/examples/localgroup/localgroup_addmembers.c
new file mode 100644
index 0000000..aa4a9b5
--- /dev/null
+++ b/source3/lib/netapi/examples/localgroup/localgroup_addmembers.c
@@ -0,0 +1,141 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupAddMembers query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ struct LOCALGROUP_MEMBERS_INFO_0 *g0;
+ struct LOCALGROUP_MEMBERS_INFO_3 *g3;
+ uint32_t total_entries = 0;
+ uint8_t *buffer = NULL;
+ uint32_t level = 3;
+ const char **names = NULL;
+ int i = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_addmembers", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname member1 member2 ...");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+
+ names = poptGetArgs(pc);
+ for (i=0; names[i] != NULL; i++) {
+ total_entries++;
+ }
+
+ switch (level) {
+ case 0:
+ status = NetApiBufferAllocate(sizeof(struct LOCALGROUP_MEMBERS_INFO_0) * total_entries,
+ (void **)&g0);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<total_entries; i++) {
+ if (!ConvertStringSidToSid(names[i], &g0[i].lgrmi0_sid)) {
+ printf("could not convert sid\n");
+ goto out;
+ }
+ }
+
+ buffer = (uint8_t *)g0;
+ break;
+ case 3:
+ status = NetApiBufferAllocate(sizeof(struct LOCALGROUP_MEMBERS_INFO_3) * total_entries,
+ (void **)&g3);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<total_entries; i++) {
+ g3[i].lgrmi3_domainandname = names[i];
+ }
+
+ buffer = (uint8_t *)g3;
+ break;
+ default:
+ break;
+ }
+
+ /* NetLocalGroupAddMembers */
+
+ status = NetLocalGroupAddMembers(hostname,
+ groupname,
+ level,
+ buffer,
+ total_entries);
+ if (status != 0) {
+ printf("NetLocalGroupAddMembers failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/localgroup/localgroup_del.c b/source3/lib/netapi/examples/localgroup/localgroup_del.c
new file mode 100644
index 0000000..a2515df
--- /dev/null
+++ b/source3/lib/netapi/examples/localgroup/localgroup_del.c
@@ -0,0 +1,83 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupDel query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_del", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ /* NetLocalGroupDel */
+
+ status = NetLocalGroupDel(hostname,
+ groupname);
+ if (status != 0) {
+ printf("NetLocalGroupDel failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/localgroup/localgroup_delmembers.c b/source3/lib/netapi/examples/localgroup/localgroup_delmembers.c
new file mode 100644
index 0000000..7bd3ec0
--- /dev/null
+++ b/source3/lib/netapi/examples/localgroup/localgroup_delmembers.c
@@ -0,0 +1,141 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupDelMembers query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ struct LOCALGROUP_MEMBERS_INFO_0 *g0;
+ struct LOCALGROUP_MEMBERS_INFO_3 *g3;
+ uint32_t total_entries = 0;
+ uint8_t *buffer = NULL;
+ uint32_t level = 3;
+ const char **names = NULL;
+ int i = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_delmembers", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname member1 member2 ...");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+
+ names = poptGetArgs(pc);
+ for (i=0; names[i] != NULL; i++) {
+ total_entries++;
+ }
+
+ switch (level) {
+ case 0:
+ status = NetApiBufferAllocate(sizeof(struct LOCALGROUP_MEMBERS_INFO_0) * total_entries,
+ (void **)&g0);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<total_entries; i++) {
+ if (!ConvertStringSidToSid(names[i], &g0[i].lgrmi0_sid)) {
+ printf("could not convert sid\n");
+ goto out;
+ }
+ }
+
+ buffer = (uint8_t *)g0;
+ break;
+ case 3:
+ status = NetApiBufferAllocate(sizeof(struct LOCALGROUP_MEMBERS_INFO_3) * total_entries,
+ (void **)&g3);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<total_entries; i++) {
+ g3[i].lgrmi3_domainandname = names[i];
+ }
+
+ buffer = (uint8_t *)g3;
+ break;
+ default:
+ break;
+ }
+
+ /* NetLocalGroupDelMembers */
+
+ status = NetLocalGroupDelMembers(hostname,
+ groupname,
+ level,
+ buffer,
+ total_entries);
+ if (status != 0) {
+ printf("NetLocalGroupDelMembers failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/localgroup/localgroup_enum.c b/source3/lib/netapi/examples/localgroup/localgroup_enum.c
new file mode 100644
index 0000000..6fe0cf4
--- /dev/null
+++ b/source3/lib/netapi/examples/localgroup/localgroup_enum.c
@@ -0,0 +1,126 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupEnum query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int i;
+
+ struct LOCALGROUP_INFO_0 *info0 = NULL;
+ struct LOCALGROUP_INFO_1 *info1 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_enum", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetLocalGroupEnum */
+
+ do {
+ status = NetLocalGroupEnum(hostname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ printf("total entries: %d\n", total_entries);
+ switch (level) {
+ case 0:
+ info0 = (struct LOCALGROUP_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct LOCALGROUP_INFO_1 *)buffer;
+ break;
+ default:
+ break;
+ }
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ printf("#%d group: %s\n", i, info0->lgrpi0_name);
+ info0++;
+ break;
+ case 1:
+ printf("#%d group: %s\n", i, info1->lgrpi1_name);
+ printf("#%d comment: %s\n", i, info1->lgrpi1_comment);
+ info1++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetLocalGroupEnum failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/localgroup/localgroup_getinfo.c b/source3/lib/netapi/examples/localgroup/localgroup_getinfo.c
new file mode 100644
index 0000000..cd8fa8c
--- /dev/null
+++ b/source3/lib/netapi/examples/localgroup/localgroup_getinfo.c
@@ -0,0 +1,112 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupGetInfo query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 0;
+ struct LOCALGROUP_INFO_0 *g0;
+ struct LOCALGROUP_INFO_1 *g1;
+ struct LOCALGROUP_INFO_1002 *g1002;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_getinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetLocalGroupGetInfo */
+
+ status = NetLocalGroupGetInfo(hostname,
+ groupname,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("NetLocalGroupGetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ switch (level) {
+ case 0:
+ g0 = (struct LOCALGROUP_INFO_0 *)buffer;
+ printf("name: %s\n", g0->lgrpi0_name);
+ break;
+ case 1:
+ g1 = (struct LOCALGROUP_INFO_1 *)buffer;
+ printf("name: %s\n", g1->lgrpi1_name);
+ printf("comment: %s\n", g1->lgrpi1_comment);
+ break;
+ case 1002:
+ g1002 = (struct LOCALGROUP_INFO_1002 *)buffer;
+ printf("comment: %s\n", g1002->lgrpi1002_comment);
+ break;
+ }
+ NetApiBufferFree(buffer);
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/localgroup/localgroup_getmembers.c b/source3/lib/netapi/examples/localgroup/localgroup_getmembers.c
new file mode 100644
index 0000000..0589870
--- /dev/null
+++ b/source3/lib/netapi/examples/localgroup/localgroup_getmembers.c
@@ -0,0 +1,165 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupGetMembers query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ char *sid_str = NULL;
+ int i;
+
+ struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL;
+ struct LOCALGROUP_MEMBERS_INFO_1 *info1 = NULL;
+ struct LOCALGROUP_MEMBERS_INFO_2 *info2 = NULL;
+ struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_getmembers", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetLocalGroupGetMembers */
+
+ do {
+ status = NetLocalGroupGetMembers(hostname,
+ groupname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ printf("total entries: %d\n", total_entries);
+ switch (level) {
+ case 0:
+ info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct LOCALGROUP_MEMBERS_INFO_1 *)buffer;
+ break;
+ case 2:
+ info2 = (struct LOCALGROUP_MEMBERS_INFO_2 *)buffer;
+ break;
+ case 3:
+ info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)buffer;
+ break;
+ default:
+ break;
+ }
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ if (ConvertSidToStringSid(info0->lgrmi0_sid,
+ &sid_str)) {
+ printf("#%d member sid: %s\n", i, sid_str);
+ free(sid_str);
+ }
+ info0++;
+ break;
+ case 1:
+ if (ConvertSidToStringSid(info1->lgrmi1_sid,
+ &sid_str)) {
+ printf("#%d member sid: %s\n", i, sid_str);
+ free(sid_str);
+ }
+ printf("#%d sid type: %d\n", i, info1->lgrmi1_sidusage);
+ printf("#%d name: %s\n", i, info1->lgrmi1_name);
+ info1++;
+ break;
+ case 2:
+ if (ConvertSidToStringSid(info2->lgrmi2_sid,
+ &sid_str)) {
+ printf("#%d member sid: %s\n", i, sid_str);
+ free(sid_str);
+ }
+ printf("#%d sid type: %d\n", i, info2->lgrmi2_sidusage);
+ printf("#%d full name: %s\n", i, info2->lgrmi2_domainandname);
+ info2++;
+ break;
+ case 3:
+ printf("#%d full name: %s\n", i, info3->lgrmi3_domainandname);
+ info3++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetLocalGroupGetMembers failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/localgroup/localgroup_setinfo.c b/source3/lib/netapi/examples/localgroup/localgroup_setinfo.c
new file mode 100644
index 0000000..efcec76
--- /dev/null
+++ b/source3/lib/netapi/examples/localgroup/localgroup_setinfo.c
@@ -0,0 +1,128 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupSetInfo query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 0;
+ struct LOCALGROUP_INFO_0 g0;
+ struct LOCALGROUP_INFO_1 g1;
+ struct LOCALGROUP_INFO_1002 g1002;
+ const char *newname = NULL;
+ const char *newcomment = NULL;
+ uint32_t parm_err = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ { "newname", 0, POPT_ARG_STRING, NULL, 'n', "New Local Group Name", "NEWNAME" },
+ { "newcomment", 0, POPT_ARG_STRING, NULL, 'c', "New Local Group Comment", "NETCOMMENT" },
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_setinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case 'n':
+ newname = poptGetOptArg(pc);
+ break;
+ case 'c':
+ newcomment = poptGetOptArg(pc);
+ break;
+ }
+
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ if (newname && !newcomment) {
+ g0.lgrpi0_name = newname;
+ buffer = (uint8_t *)&g0;
+ level = 0;
+ } else if (newcomment && !newname) {
+ g1002.lgrpi1002_comment = newcomment;
+ buffer = (uint8_t *)&g1002;
+ level = 1002;
+ } else if (newname && newcomment) {
+ g1.lgrpi1_name = newname;
+ g1.lgrpi1_comment = newcomment;
+ buffer = (uint8_t *)&g1;
+ level = 1;
+ } else {
+ printf("not enough input\n");
+ goto out;
+ }
+
+ /* NetLocalGroupSetInfo */
+
+ status = NetLocalGroupSetInfo(hostname,
+ groupname,
+ level,
+ buffer,
+ &parm_err);
+ if (status != 0) {
+ printf("NetLocalGroupSetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/localgroup/localgroup_setmembers.c b/source3/lib/netapi/examples/localgroup/localgroup_setmembers.c
new file mode 100644
index 0000000..c35f2bb
--- /dev/null
+++ b/source3/lib/netapi/examples/localgroup/localgroup_setmembers.c
@@ -0,0 +1,146 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupSetMembers query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ struct LOCALGROUP_MEMBERS_INFO_0 *g0;
+ struct LOCALGROUP_MEMBERS_INFO_3 *g3;
+ uint32_t total_entries = 0;
+ uint8_t *buffer = NULL;
+ uint32_t level = 3;
+ const char **names = NULL;
+ int i = 0;
+ size_t buf_size = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_setmembers", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname member1 member2 ...");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+
+ names = poptGetArgs(pc);
+ for (i=0; names[i] != NULL; i++) {
+ total_entries++;
+ }
+
+ switch (level) {
+ case 0:
+ buf_size = sizeof(struct LOCALGROUP_MEMBERS_INFO_0) * total_entries;
+
+ status = NetApiBufferAllocate(buf_size, (void **)&g0);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<total_entries; i++) {
+ if (!ConvertStringSidToSid(names[i], &g0[i].lgrmi0_sid)) {
+ printf("could not convert sid\n");
+ goto out;
+ }
+ }
+
+ buffer = (uint8_t *)g0;
+ break;
+ case 3:
+ buf_size = sizeof(struct LOCALGROUP_MEMBERS_INFO_3) * total_entries;
+
+ status = NetApiBufferAllocate(buf_size, (void **)&g3);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<total_entries; i++) {
+ g3[i].lgrmi3_domainandname = names[i];
+ }
+
+ buffer = (uint8_t *)g3;
+ break;
+ default:
+ break;
+ }
+
+ /* NetLocalGroupSetMembers */
+
+ status = NetLocalGroupSetMembers(hostname,
+ groupname,
+ level,
+ buffer,
+ total_entries);
+ if (status != 0) {
+ printf("NetLocalGroupSetMembers failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ NetApiBufferFree(buffer);
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/netdomjoin-gui/logo-small.png b/source3/lib/netapi/examples/netdomjoin-gui/logo-small.png
new file mode 100644
index 0000000..f041198
--- /dev/null
+++ b/source3/lib/netapi/examples/netdomjoin-gui/logo-small.png
Binary files differ
diff --git a/source3/lib/netapi/examples/netdomjoin-gui/logo.png b/source3/lib/netapi/examples/netdomjoin-gui/logo.png
new file mode 100644
index 0000000..6df4ace
--- /dev/null
+++ b/source3/lib/netapi/examples/netdomjoin-gui/logo.png
Binary files differ
diff --git a/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c b/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c
new file mode 100644
index 0000000..ca599d3
--- /dev/null
+++ b/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c
@@ -0,0 +1,1888 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Join Support (gtk + netapi)
+ * Copyright (C) Guenther Deschner 2007-2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <netdb.h>
+
+#include <gtk/gtk.h>
+#include <glib/gprintf.h>
+
+#include <netapi.h>
+
+#define MAX_CRED_LEN 256
+#define MAX_NETBIOS_NAME_LEN 15
+
+#define SAMBA_ICON_PATH "/usr/share/pixmaps/samba/samba.ico"
+#define SAMBA_IMAGE_PATH "/usr/share/pixmaps/samba/logo.png"
+#define SAMBA_IMAGE_PATH_SMALL "/usr/share/pixmaps/samba/logo-small.png"
+
+#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
+
+static gboolean verbose = FALSE;
+
+typedef struct join_state {
+ struct libnetapi_ctx *ctx;
+ GtkWidget *window_main;
+ GtkWidget *window_parent;
+ GtkWidget *window_do_change;
+ GtkWidget *window_creds_prompt;
+ GtkWidget *entry_account;
+ GtkWidget *entry_password;
+ GtkWidget *entry_domain;
+ GtkWidget *entry_ou_list;
+ GtkWidget *entry_workgroup;
+ GtkWidget *button_ok;
+ GtkWidget *button_apply;
+ GtkWidget *button_ok_creds;
+ GtkWidget *button_get_ous;
+ GtkWidget *label_reboot;
+ GtkWidget *label_current_name_buffer;
+ GtkWidget *label_current_name_type;
+ GtkWidget *label_full_computer_name;
+ GtkWidget *label_winbind;
+ uint16_t name_type_initial;
+ uint16_t name_type_new;
+ char *name_buffer_initial;
+ char *name_buffer_new;
+ char *password;
+ char *account;
+ char *comment;
+ char *comment_new;
+ char *my_fqdn;
+ char *my_dnsdomain;
+ char *my_hostname;
+ uint16_t server_role;
+ gboolean settings_changed;
+ gboolean hostname_changed;
+ uint32_t stored_num_ous;
+ char *target_hostname;
+ uid_t uid;
+} join_state;
+
+static void callback_creds_prompt(GtkWidget *widget,
+ gpointer data,
+ const char *label_string,
+ gpointer cont_fn);
+
+
+static void debug(const char *format, ...)
+{
+ va_list args;
+
+ if (!verbose) {
+ return;
+ }
+
+ va_start(args, format);
+ g_vprintf(format, args);
+ va_end(args);
+}
+
+static gboolean callback_delete_event(GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data)
+{
+ gtk_main_quit();
+ return FALSE;
+}
+
+static void callback_do_close_data(GtkWidget *widget,
+ gpointer data)
+{
+ debug("callback_do_close_data called\n");
+
+ if (data) {
+ gtk_widget_destroy(GTK_WIDGET(data));
+ }
+}
+
+static void callback_do_close_widget(GtkWidget *widget,
+ gpointer data)
+{
+ debug("callback_do_close_widget called\n");
+
+ if (widget) {
+ gtk_widget_destroy(widget);
+ }
+}
+
+static void callback_do_freeauth(GtkWidget *widget,
+ gpointer data)
+{
+ struct join_state *state = (struct join_state *)data;
+
+ debug("callback_do_freeauth called\n");
+
+ SAFE_FREE(state->account);
+ SAFE_FREE(state->password);
+
+ if (state->window_creds_prompt) {
+ gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
+ state->window_creds_prompt = NULL;
+ }
+}
+
+static void callback_do_freeauth_and_close(GtkWidget *widget,
+ gpointer data)
+{
+ struct join_state *state = (struct join_state *)data;
+
+ debug("callback_do_freeauth_and_close called\n");
+
+ SAFE_FREE(state->account);
+ SAFE_FREE(state->password);
+
+ if (state->window_creds_prompt) {
+ gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
+ state->window_creds_prompt = NULL;
+ }
+ if (state->window_do_change) {
+ gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
+ state->window_do_change = NULL;
+ }
+}
+
+static void free_join_state(struct join_state *s)
+{
+ SAFE_FREE(s->name_buffer_initial);
+ SAFE_FREE(s->name_buffer_new);
+ SAFE_FREE(s->password);
+ SAFE_FREE(s->account);
+ SAFE_FREE(s->comment);
+ SAFE_FREE(s->comment_new);
+ SAFE_FREE(s->my_fqdn);
+ SAFE_FREE(s->my_dnsdomain);
+ SAFE_FREE(s->my_hostname);
+}
+
+static void do_cleanup(struct join_state *state)
+{
+ libnetapi_free(state->ctx);
+ free_join_state(state);
+}
+
+static void callback_apply_description_change(GtkWidget *widget,
+ gpointer data)
+{
+ struct join_state *state = (struct join_state *)data;
+ NET_API_STATUS status = 0;
+ uint32_t parm_err = 0;
+ struct SERVER_INFO_1005 info1005;
+ GtkWidget *dialog;
+
+ info1005.sv1005_comment = state->comment_new;
+
+ status = NetServerSetInfo(state->target_hostname,
+ 1005,
+ (uint8_t *)&info1005,
+ &parm_err);
+ if (status) {
+ debug("NetServerSetInfo failed with: %s\n",
+ libnetapi_errstr(status));
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "Failed to change computer description: %s.",
+ libnetapi_get_error_string(state->ctx, status));
+ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_main));
+
+ g_signal_connect_swapped(dialog, "response",
+ G_CALLBACK(gtk_widget_destroy),
+ dialog);
+
+ gtk_widget_show(dialog);
+ return;
+ }
+
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
+}
+
+static void callback_do_exit(GtkWidget *widget,
+ gpointer data)
+{
+#if 0
+ GtkWidget *dialog;
+ gint result;
+#endif
+ struct join_state *state = (struct join_state *)data;
+
+ if (!state->settings_changed) {
+ callback_delete_event(NULL, NULL, NULL);
+ return;
+ }
+
+#if 0
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_YES_NO,
+ "You must restart your computer before the new settings will take effect.");
+ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
+ switch (result) {
+ case GTK_RESPONSE_YES:
+ g_print("would reboot here\n");
+ break;
+ case GTK_RESPONSE_NO:
+ default:
+ break;
+ }
+ if (dialog) {
+ gtk_widget_destroy(GTK_WIDGET(dialog));
+ }
+#endif
+ if (state->window_main) {
+ gtk_widget_destroy(GTK_WIDGET(state->window_main));
+ state->window_main = NULL;
+ }
+ do_cleanup(state);
+ exit(0);
+}
+
+
+static void callback_do_reboot(GtkWidget *widget,
+ gpointer data,
+ gpointer data2)
+{
+ GtkWidget *dialog;
+ struct join_state *state = (struct join_state *)data2;
+
+ debug("callback_do_reboot\n");
+
+ state->settings_changed = TRUE;
+ dialog = gtk_message_dialog_new(GTK_WINDOW(data),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ "You must restart this computer for the changes to take effect.");
+ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
+#if 0
+ g_signal_connect_swapped(dialog, "response",
+ G_CALLBACK(gtk_widget_destroy),
+ dialog);
+
+ debug("showing dialog\n");
+ gtk_widget_show(dialog);
+#else
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(GTK_WIDGET(dialog));
+#endif
+
+ gtk_label_set_text(GTK_LABEL(state->label_reboot),
+ "Changes will take effect after you restart this computer");
+
+ debug("destroying do_change window\n");
+ gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
+
+ {
+ uint32_t status;
+ const char *buffer;
+ uint16_t type;
+
+ status = NetGetJoinInformation(state->target_hostname,
+ &buffer,
+ &type);
+ if (status != 0) {
+ g_print("failed to query status\n");
+ return;
+ }
+
+ debug("got new status: %s\n", buffer);
+
+ SAFE_FREE(state->name_buffer_new);
+ state->name_buffer_new = strdup(buffer);
+ state->name_type_new = type;
+ state->name_buffer_initial = strdup(buffer);
+ state->name_type_initial = type;
+ NetApiBufferFree((void *)buffer);
+
+ gtk_label_set_text(GTK_LABEL(state->label_current_name_buffer),
+ state->name_buffer_new);
+ if (state->name_type_new == NetSetupDomainName) {
+ gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
+ "Domain:");
+ } else {
+ gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
+ "Workgroup:");
+ }
+ }
+}
+
+static void callback_return_username(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text;
+ struct join_state *state = (struct join_state *)data;
+ debug("callback_return_username called\n");
+ if (!widget) {
+ return;
+ }
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+ if (!entry_text) {
+ return;
+ }
+ debug("callback_return_username: %s\n", entry_text);
+ SAFE_FREE(state->account);
+ state->account = strdup(entry_text);
+}
+
+static void callback_return_username_and_enter(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text;
+ struct join_state *state = (struct join_state *)data;
+ if (!widget) {
+ return;
+ }
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+ if (!entry_text) {
+ return;
+ }
+ debug("callback_return_username_and_enter: %s\n", entry_text);
+ SAFE_FREE(state->account);
+ state->account = strdup(entry_text);
+ g_signal_emit_by_name(state->button_ok_creds, "clicked");
+}
+
+static void callback_return_password(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text;
+ struct join_state *state = (struct join_state *)data;
+ debug("callback_return_password called\n");
+ if (!widget) {
+ return;
+ }
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+ if (!entry_text) {
+ return;
+ }
+#ifdef DEBUG_PASSWORD
+ debug("callback_return_password: %s\n", entry_text);
+#else
+ debug("callback_return_password: (not printed)\n");
+#endif
+ SAFE_FREE(state->password);
+ state->password = strdup(entry_text);
+}
+
+static void callback_return_password_and_enter(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text;
+ struct join_state *state = (struct join_state *)data;
+ if (!widget) {
+ return;
+ }
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+ if (!entry_text) {
+ return;
+ }
+#ifdef DEBUG_PASSWORD
+ debug("callback_return_password_and_enter: %s\n", entry_text);
+#else
+ debug("callback_return_password_and_enter: (not printed)\n");
+#endif
+ SAFE_FREE(state->password);
+ state->password = strdup(entry_text);
+ g_signal_emit_by_name(state->button_ok_creds, "clicked");
+}
+
+static void callback_do_storeauth(GtkWidget *widget,
+ gpointer data)
+{
+ struct join_state *state = (struct join_state *)data;
+
+ debug("callback_do_storeauth called\n");
+
+ SAFE_FREE(state->account);
+ SAFE_FREE(state->password);
+
+ callback_return_username(state->entry_account, (gpointer)state);
+ callback_return_password(state->entry_password, (gpointer)state);
+
+ if (state->window_creds_prompt) {
+ gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
+ state->window_creds_prompt = NULL;
+ }
+}
+
+static void callback_continue(GtkWidget *widget,
+ gpointer data)
+{
+ struct join_state *state = (struct join_state *)data;
+
+ gtk_widget_grab_focus(GTK_WIDGET(state->button_ok));
+ g_signal_emit_by_name(state->button_ok, "clicked");
+}
+
+static void callback_do_storeauth_and_continue(GtkWidget *widget,
+ gpointer data)
+{
+ callback_do_storeauth(widget, data);
+ callback_continue(NULL, data);
+}
+
+static void callback_do_storeauth_and_scan(GtkWidget *widget,
+ gpointer data)
+{
+ struct join_state *state = (struct join_state *)data;
+ callback_do_storeauth(widget, data);
+ g_signal_emit_by_name(state->button_get_ous, "clicked");
+}
+
+static void callback_do_hostname_change(GtkWidget *widget,
+ gpointer data)
+{
+ GtkWidget *dialog;
+ const char *str = NULL;
+
+ struct join_state *state = (struct join_state *)data;
+
+ switch (state->name_type_initial) {
+ case NetSetupDomainName: {
+#if 0
+ NET_API_STATUS status;
+ const char *newname;
+ char *p = NULL;
+
+ newname = strdup(gtk_label_get_text(GTK_LABEL(state->label_full_computer_name)));
+ if (!newname) {
+ return;
+ }
+
+ p = strchr(newname, '.');
+ if (p) {
+ *p = '\0';
+ }
+
+ if (!state->account || !state->password) {
+ debug("callback_do_hostname_change: no creds yet\n");
+ callback_creds_prompt(NULL, state,
+ "Enter the name and password of an account with permission to change a computer name in a the domain.",
+ callback_do_storeauth_and_continue);
+ }
+
+ if (!state->account || !state->password) {
+ debug("callback_do_hostname_change: still no creds???\n");
+ return;
+ }
+
+ status = NetRenameMachineInDomain(state->target_hostname,
+ newname,
+ state->account,
+ state->password,
+ NETSETUP_ACCT_CREATE);
+ SAFE_FREE(newname);
+ /* we renamed the machine in the domain */
+ if (status == 0) {
+ return;
+ }
+ str = libnetapi_get_error_string(state->ctx, status);
+#else
+ str = "To be implemented: call NetRenameMachineInDomain\n";
+#endif
+ break;
+ }
+ case NetSetupWorkgroupName:
+ str = "To be implemented: call SetComputerNameEx\n";
+ break;
+ default:
+ break;
+ }
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "%s",str);
+
+ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_main));
+ g_signal_connect_swapped(dialog, "response",
+ G_CALLBACK(gtk_widget_destroy),
+ dialog);
+ gtk_widget_show(dialog);
+}
+
+static void callback_creds_prompt(GtkWidget *widget,
+ gpointer data,
+ const char *label_string,
+ gpointer cont_fn)
+{
+ GtkWidget *window;
+ GtkWidget *box1;
+ GtkWidget *bbox;
+ GtkWidget *button;
+ GtkWidget *label;
+
+ struct join_state *state = (struct join_state *)data;
+
+ debug("callback_creds_prompt\n");
+
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_modal(GTK_WINDOW(window), TRUE);
+
+ gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
+ gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
+ gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
+ gtk_widget_set_size_request(GTK_WIDGET(window), 380, 280);
+ gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
+ gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(state->window_do_change));
+ gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
+
+ g_signal_connect(G_OBJECT(window), "delete_event",
+ G_CALLBACK(callback_do_close_widget), NULL);
+
+ state->window_creds_prompt = window;
+ gtk_container_set_border_width(GTK_CONTAINER(window), 10);
+
+ box1 = gtk_vbox_new(FALSE, 0);
+
+ gtk_container_add(GTK_CONTAINER(window), box1);
+
+ label = gtk_label_new(label_string);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+
+ gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
+
+ gtk_widget_show(label);
+
+ /* USER NAME */
+ label = gtk_label_new("User name:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+
+ state->entry_account = gtk_entry_new();
+ gtk_entry_set_max_length(GTK_ENTRY(state->entry_account), MAX_CRED_LEN);
+ g_signal_connect(G_OBJECT(state->entry_account), "activate",
+ G_CALLBACK(callback_return_username_and_enter),
+ (gpointer)state);
+ gtk_editable_select_region(GTK_EDITABLE(state->entry_account),
+ 0, GTK_ENTRY(state->entry_account)->text_length);
+ gtk_box_pack_start(GTK_BOX(box1), state->entry_account, TRUE, TRUE, 0);
+ gtk_widget_show(state->entry_account);
+
+ /* PASSWORD */
+ label = gtk_label_new("Password:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+
+ state->entry_password = gtk_entry_new();
+ gtk_entry_set_max_length(GTK_ENTRY(state->entry_password), MAX_CRED_LEN);
+ gtk_entry_set_visibility(GTK_ENTRY(state->entry_password), FALSE);
+ g_signal_connect(G_OBJECT(state->entry_password), "activate",
+ G_CALLBACK(callback_return_password_and_enter),
+ (gpointer)state);
+ gtk_editable_set_editable(GTK_EDITABLE(state->entry_password), TRUE);
+ gtk_editable_select_region(GTK_EDITABLE(state->entry_password),
+ 0, GTK_ENTRY(state->entry_password)->text_length);
+ gtk_box_pack_start(GTK_BOX(box1), state->entry_password, TRUE, TRUE, 0);
+ gtk_widget_show(state->entry_password);
+
+ /* BUTTONS */
+ bbox = gtk_hbutton_box_new();
+ gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
+ gtk_container_add(GTK_CONTAINER(box1), bbox);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
+ gtk_box_set_spacing(GTK_BOX(bbox), 10);
+
+ state->button_ok_creds = gtk_button_new_from_stock(GTK_STOCK_OK);
+ gtk_widget_grab_focus(GTK_WIDGET(state->button_ok_creds));
+ gtk_container_add(GTK_CONTAINER(bbox), state->button_ok_creds);
+ g_signal_connect(G_OBJECT(state->button_ok_creds), "clicked",
+ G_CALLBACK(cont_fn),
+ (gpointer)state);
+ gtk_widget_show(state->button_ok_creds);
+
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ gtk_container_add(GTK_CONTAINER(bbox), button);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(callback_do_freeauth),
+ (gpointer)state);
+ gtk_widget_show_all(window);
+}
+
+static void callback_do_join(GtkWidget *widget,
+ gpointer data)
+{
+ GtkWidget *dialog;
+
+ NET_API_STATUS status;
+ const char *err_str = NULL;
+ uint32_t join_flags = 0;
+ uint32_t unjoin_flags = 0;
+ gboolean domain_join = FALSE;
+ gboolean try_unjoin = FALSE;
+ gboolean join_creds_required = TRUE;
+ gboolean unjoin_creds_required = TRUE;
+ const char *new_workgroup_type = NULL;
+ const char *initial_workgroup_type = NULL;
+ const char *account_ou = NULL;
+
+ struct join_state *state = (struct join_state *)data;
+
+ if (state->hostname_changed) {
+ callback_do_hostname_change(NULL, state);
+ return;
+ }
+
+ switch (state->name_type_initial) {
+ case NetSetupWorkgroupName:
+ initial_workgroup_type = "workgroup";
+ break;
+ case NetSetupDomainName:
+ initial_workgroup_type = "domain";
+ break;
+ default:
+ break;
+ }
+
+ switch (state->name_type_new) {
+ case NetSetupWorkgroupName:
+ new_workgroup_type = "workgroup";
+ break;
+ case NetSetupDomainName:
+ new_workgroup_type = "domain";
+ break;
+ default:
+ break;
+ }
+
+ account_ou = gtk_combo_box_get_active_text(GTK_COMBO_BOX(state->entry_ou_list));
+ if (account_ou && strlen(account_ou) == 0) {
+ account_ou = NULL;
+ }
+
+ if ((state->name_type_initial != NetSetupDomainName) &&
+ (state->name_type_new != NetSetupDomainName)) {
+ join_creds_required = FALSE;
+ unjoin_creds_required = FALSE;
+ }
+
+ if (state->name_type_new == NetSetupDomainName) {
+ domain_join = TRUE;
+ join_creds_required = TRUE;
+ join_flags = NETSETUP_JOIN_DOMAIN |
+ NETSETUP_ACCT_CREATE |
+ NETSETUP_DOMAIN_JOIN_IF_JOINED; /* for testing */
+ }
+
+ if ((state->name_type_initial == NetSetupDomainName) &&
+ (state->name_type_new == NetSetupWorkgroupName)) {
+ try_unjoin = TRUE;
+ unjoin_creds_required = TRUE;
+ join_creds_required = FALSE;
+ unjoin_flags = NETSETUP_JOIN_DOMAIN |
+ NETSETUP_ACCT_DELETE |
+ NETSETUP_IGNORE_UNSUPPORTED_FLAGS;
+ }
+
+ if (try_unjoin) {
+
+ debug("callback_do_join: Unjoining\n");
+
+ if (unjoin_creds_required) {
+ if (!state->account || !state->password) {
+ debug("callback_do_join: no creds yet\n");
+ callback_creds_prompt(NULL, state,
+ "Enter the name and password of an account with permission to leave the domain.",
+ callback_do_storeauth_and_continue);
+ }
+
+ if (!state->account || !state->password) {
+ debug("callback_do_join: still no creds???\n");
+ return;
+ }
+ }
+
+ status = NetUnjoinDomain(state->target_hostname,
+ state->account,
+ state->password,
+ unjoin_flags);
+ if (status != 0) {
+ callback_do_freeauth(NULL, state);
+ err_str = libnetapi_get_error_string(state->ctx, status);
+ g_print("callback_do_join: failed to unjoin (%s)\n",
+ err_str);
+#if 0
+
+ /* in fact we shouldn't annoy the user with an error message here */
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "The following error occurred attempting to unjoin the %s: \"%s\": %s",
+ initial_workgroup_type,
+ state->name_buffer_initial,
+ err_str);
+ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+#endif
+ }
+
+ }
+
+ /* before prompting for creds, make sure we can find a dc */
+
+ if (domain_join) {
+
+ struct DOMAIN_CONTROLLER_INFO *dc_info = NULL;
+
+ status = DsGetDcName(NULL,
+ state->name_buffer_new,
+ NULL,
+ NULL,
+ 0,
+ &dc_info);
+ if (status != 0) {
+ err_str = libnetapi_get_error_string(state->ctx, status);
+ g_print("callback_do_join: failed find dc (%s)\n", err_str);
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "Failed to find a domain controller for domain: \"%s\": %s",
+ state->name_buffer_new,
+ err_str);
+
+ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
+ g_signal_connect_swapped(dialog, "response",
+ G_CALLBACK(gtk_widget_destroy),
+ dialog);
+
+ gtk_widget_show(dialog);
+
+ return;
+ }
+ }
+
+ if (join_creds_required) {
+ if (!state->account || !state->password) {
+ debug("callback_do_join: no creds yet\n");
+ callback_creds_prompt(NULL, state,
+ "Enter the name and password of an account with permission to join the domain.",
+ callback_do_storeauth_and_continue);
+ }
+
+ if (!state->account || !state->password) {
+ debug("callback_do_join: still no creds???\n");
+ return;
+ }
+ }
+
+ debug("callback_do_join: Joining a %s named %s using join_flags 0x%08x ",
+ new_workgroup_type,
+ state->name_buffer_new,
+ join_flags);
+ if (domain_join) {
+ debug("as %s ", state->account);
+#ifdef DEBUG_PASSWORD
+ debug("with %s ", state->password);
+#endif
+ }
+ debug("\n");
+
+ status = NetJoinDomain(state->target_hostname,
+ state->name_buffer_new,
+ account_ou,
+ state->account,
+ state->password,
+ join_flags);
+ if (status != 0) {
+ callback_do_freeauth(NULL, state);
+ err_str = libnetapi_get_error_string(state->ctx, status);
+ g_print("callback_do_join: failed to join (%s)\n", err_str);
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "The following error occurred attempting to join the %s: \"%s\": %s",
+ new_workgroup_type,
+ state->name_buffer_new,
+ err_str);
+
+ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
+ g_signal_connect_swapped(dialog, "response",
+ G_CALLBACK(gtk_widget_destroy),
+ dialog);
+
+ gtk_widget_show(dialog);
+
+ return;
+ }
+
+ debug("callback_do_join: Successfully joined %s\n",
+ new_workgroup_type);
+
+ callback_do_freeauth(NULL, state);
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ "Welcome to the %s %s.",
+ state->name_buffer_new,
+ new_workgroup_type);
+
+ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+
+ callback_do_reboot(NULL, state->window_parent, state);
+}
+
+static void callback_enter_hostname_and_unlock(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text = NULL;
+ char *str = NULL;
+ struct join_state *state = (struct join_state *)data;
+
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+ debug("callback_enter_hostname_and_unlock: %s\n", entry_text);
+ if (!entry_text || entry_text[0] == 0) {
+ state->hostname_changed = FALSE;
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+ gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), "");
+ return;
+ }
+ if (strcasecmp(state->my_hostname, entry_text) == 0) {
+ state->hostname_changed = FALSE;
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+ /* return; */
+ } else {
+ state->hostname_changed = TRUE;
+ }
+
+ if (state->name_type_initial == NetSetupDomainName) {
+ if (asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain) == -1) {
+ return;
+ }
+ } else {
+ if (asprintf(&str, "%s.", entry_text) == -1) {
+ return;
+ }
+ }
+ gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
+ free(str);
+
+ if (state->hostname_changed && entry_text && entry_text[0] != 0 && entry_text[0] != '.') {
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
+ }
+}
+
+static void callback_enter_computer_description_and_unlock(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text = NULL;
+ struct join_state *state = (struct join_state *)data;
+ int string_unchanged = FALSE;
+
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+ debug("callback_enter_computer_description_and_unlock: %s\n",
+ entry_text);
+#if 0
+ if (!entry_text || entry_text[0] == 0) {
+ string_unchanged = 1;
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
+ FALSE);
+ return;
+ }
+#endif
+ if (entry_text && state->comment && strcasecmp(state->comment, entry_text) == 0) {
+ string_unchanged = TRUE;
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
+ FALSE);
+ return;
+ }
+
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), TRUE);
+ SAFE_FREE(state->comment_new);
+ state->comment_new = strdup(entry_text);
+
+}
+
+
+static void callback_enter_workgroup_and_unlock(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text = NULL;
+ struct join_state *state = (struct join_state *)data;
+
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+ debug("callback_enter_workgroup_and_unlock: %s\n", entry_text);
+ if (!entry_text || entry_text[0] == 0) {
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+ return;
+ }
+ if ((strcasecmp(state->name_buffer_initial, entry_text) == 0) &&
+ (state->name_type_initial == NetSetupWorkgroupName)) {
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+ return;
+ }
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
+ SAFE_FREE(state->name_buffer_new);
+ state->name_buffer_new = strdup(entry_text);
+ state->name_type_new = NetSetupWorkgroupName;
+}
+
+static void callback_enter_domain_and_unlock(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text = NULL;
+ struct join_state *state = (struct join_state *)data;
+
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+ debug("callback_enter_domain_and_unlock: %s\n", entry_text);
+ if (!entry_text || entry_text[0] == 0) {
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+ return;
+ }
+ if ((strcasecmp(state->name_buffer_initial, entry_text) == 0) &&
+ (state->name_type_initial == NetSetupDomainName)) {
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+ return;
+ }
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(state->entry_ou_list), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), TRUE);
+ SAFE_FREE(state->name_buffer_new);
+ state->name_buffer_new = strdup(entry_text);
+ state->name_type_new = NetSetupDomainName;
+}
+
+static void callback_apply_continue(GtkWidget *widget,
+ gpointer data)
+{
+ struct join_state *state = (struct join_state *)data;
+
+ gtk_widget_grab_focus(GTK_WIDGET(state->button_apply));
+ g_signal_emit_by_name(state->button_apply, "clicked");
+}
+
+static void callback_do_join_workgroup(GtkWidget *widget,
+ gpointer data)
+{
+ struct join_state *state = (struct join_state *)data;
+ debug("callback_do_join_workgroup choosen\n");
+ gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
+ gtk_widget_grab_focus(GTK_WIDGET(state->entry_workgroup));
+ gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(state->entry_ou_list), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), FALSE);
+ callback_enter_workgroup_and_unlock(state->entry_workgroup, state); /* TEST */
+}
+
+static void callback_do_join_domain(GtkWidget *widget,
+ gpointer data)
+{
+ struct join_state *state = (struct join_state *)data;
+ debug("callback_do_join_domain choosen\n");
+ gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), TRUE);
+ gtk_widget_grab_focus(GTK_WIDGET(state->entry_domain));
+ gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), FALSE);
+ callback_enter_domain_and_unlock(state->entry_domain, state); /* TEST */
+}
+
+static void callback_do_getous(GtkWidget *widget,
+ gpointer data)
+{
+ NET_API_STATUS status;
+ uint32_t num_ous = 0;
+ const char **ous = NULL;
+ int i;
+ const char *domain = NULL;
+ struct DOMAIN_CONTROLLER_INFO *dc_info = NULL;
+ const char *err_str = NULL;
+ GtkWidget *dialog;
+
+ struct join_state *state = (struct join_state *)data;
+
+ debug("callback_do_getous called\n");
+
+ domain = state->name_buffer_new ? state->name_buffer_new : state->name_buffer_initial;
+
+ status = DsGetDcName(NULL,
+ domain,
+ NULL,
+ NULL,
+ 0,
+ &dc_info);
+ if (status != 0) {
+ err_str = libnetapi_get_error_string(state->ctx, status);
+ g_print("callback_do_getous: failed find dc (%s)\n", err_str);
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "Failed to find a domain controller for domain: \"%s\": %s",
+ domain,
+ err_str);
+
+ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
+ g_signal_connect_swapped(dialog, "response",
+ G_CALLBACK(gtk_widget_destroy),
+ dialog);
+
+ gtk_widget_show(dialog);
+
+ return;
+ }
+
+ if (!state->account || !state->password) {
+ debug("callback_do_getous: no creds yet\n");
+ callback_creds_prompt(NULL, state,
+ "Enter the name and password of an account with permission to join the domain.",
+ callback_do_storeauth_and_scan);
+ }
+
+ if (!state->account || !state->password) {
+ debug("callback_do_getous: still no creds ???\n");
+ return;
+ }
+
+ status = NetGetJoinableOUs(state->target_hostname,
+ domain,
+ state->account,
+ state->password,
+ &num_ous, &ous);
+ if (status != NET_API_STATUS_SUCCESS) {
+ callback_do_freeauth(NULL, state);
+ debug("failed to call NetGetJoinableOUs: %s\n",
+ libnetapi_get_error_string(state->ctx, status));
+ dialog = gtk_message_dialog_new(NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ "Failed to query joinable OUs: %s",
+ libnetapi_get_error_string(state->ctx, status));
+ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ return;
+ }
+
+ for (i=0; i<state->stored_num_ous; i++) {
+ gtk_combo_box_remove_text(GTK_COMBO_BOX(state->entry_ou_list), 0);
+ }
+ for (i=0; i<num_ous && ous[i] != NULL; i++) {
+ gtk_combo_box_append_text(GTK_COMBO_BOX(state->entry_ou_list),
+ ous[i]);
+ }
+ NetApiBufferFree(ous);
+ state->stored_num_ous = num_ous;
+ gtk_combo_box_set_active(GTK_COMBO_BOX(state->entry_ou_list), num_ous-1);
+}
+
+static void callback_do_change(GtkWidget *widget,
+ gpointer data)
+{
+ GtkWidget *window;
+ GtkWidget *box1;
+ GtkWidget *bbox;
+ GtkWidget *button_workgroup;
+ GtkWidget *button_domain;
+ GtkWidget *button;
+ GtkWidget *label;
+ GtkWidget *frame_horz;
+ GtkWidget *vbox;
+ GtkWidget *entry;
+ GSList *group;
+
+ struct join_state *state = (struct join_state *)data;
+
+ debug("callback_do_change called\n");
+
+#if 0
+ /* FIXME: add proper warnings for Samba as a DC */
+ if (state->server_role == 3) {
+ GtkWidget *dialog;
+ callback_do_freeauth(NULL, state);
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "Domain controller cannot be moved from one domain to another, they must first be demoted. Renaming this domain controller may cause it to become temporarily unavailable to users and computers. For information on renaming domain controllers, including alternate renaming methods, see Help and Support. To continue renaming this domain controller, click OK.");
+ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ g_signal_connect_swapped(dialog, "response",
+ G_CALLBACK(gtk_widget_destroy),
+ dialog);
+
+ gtk_widget_show(dialog);
+ return;
+ }
+#endif
+
+ state->button_ok = gtk_button_new_from_stock(GTK_STOCK_OK);
+ state->button_get_ous = gtk_button_new_with_label("Scan for joinable OUs");
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_modal(GTK_WINDOW(window), TRUE);
+
+ gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
+ gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
+ gtk_widget_set_size_request(GTK_WIDGET(window), 480, 650);
+ gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
+ gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(state->window_main));
+ gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
+
+ g_signal_connect(G_OBJECT(window), "delete_event",
+ G_CALLBACK(callback_do_close_widget), NULL);
+
+ gtk_container_set_border_width(GTK_CONTAINER(window), 10);
+
+ box1 = gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(window), box1);
+
+ label = gtk_label_new("You can change the name and membership of this computer. Changes may affect access to network resources.");
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
+ gtk_widget_show(label);
+
+ /* COMPUTER NAME */
+ label = gtk_label_new("Computer name:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
+ gtk_widget_show(label);
+
+ state->label_full_computer_name = gtk_label_new(NULL);
+ {
+ entry = gtk_entry_new();
+ gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_NETBIOS_NAME_LEN);
+ g_signal_connect(G_OBJECT(entry), "changed",
+ G_CALLBACK(callback_enter_hostname_and_unlock),
+ (gpointer)state);
+ gtk_entry_set_text(GTK_ENTRY(entry), state->my_hostname);
+ gtk_editable_select_region(GTK_EDITABLE(entry),
+ 0, GTK_ENTRY(entry)->text_length);
+
+ gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
+ gtk_box_pack_start(GTK_BOX(box1), entry, TRUE, TRUE, 0);
+ gtk_widget_show(entry);
+ }
+
+ /* FULL COMPUTER NAME */
+ label = gtk_label_new("Full computer name:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
+ gtk_widget_show(label);
+
+ {
+ const gchar *entry_text;
+ char *str = NULL;
+ entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
+ if (state->name_type_initial == NetSetupDomainName) {
+ if (asprintf(&str, "%s.%s", entry_text,
+ state->my_dnsdomain) == -1) {
+ return;
+ }
+ } else {
+ if (asprintf(&str, "%s.", entry_text) == -1) {
+ return;
+ }
+ }
+ gtk_label_set_text(GTK_LABEL(state->label_full_computer_name),
+ str);
+ free(str);
+ gtk_misc_set_alignment(GTK_MISC(state->label_full_computer_name), 0, 0);
+ gtk_box_pack_start(GTK_BOX(box1),
+ state->label_full_computer_name, TRUE, TRUE, 0);
+ gtk_widget_show(state->label_full_computer_name);
+ }
+
+ /* BOX */
+ frame_horz = gtk_frame_new ("Member Of");
+ gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
+ gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
+
+ /* TWO ENTRIES */
+ state->entry_workgroup = gtk_entry_new();
+ state->entry_domain = gtk_entry_new();
+
+ /* DOMAIN */
+ button_domain = gtk_radio_button_new_with_label(NULL, "Domain");
+ if (state->name_type_initial == NetSetupDomainName) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_domain), TRUE);
+ }
+ gtk_box_pack_start(GTK_BOX(vbox), button_domain, TRUE, TRUE, 0);
+ g_signal_connect(G_OBJECT(button_domain), "clicked",
+ G_CALLBACK(callback_do_join_domain),
+ (gpointer)state);
+
+ {
+ gtk_entry_set_max_length(GTK_ENTRY(state->entry_domain), 50);
+ g_signal_connect(G_OBJECT(state->entry_domain), "changed",
+ G_CALLBACK(callback_enter_domain_and_unlock),
+ (gpointer)state);
+ g_signal_connect(G_OBJECT(state->entry_domain), "activate",
+ G_CALLBACK(callback_continue),
+ (gpointer)state);
+ if (state->name_type_initial == NetSetupDomainName) {
+ gtk_entry_set_text(GTK_ENTRY(state->entry_domain),
+ state->name_buffer_initial);
+ gtk_widget_set_sensitive(state->entry_workgroup, FALSE);
+ gtk_widget_set_sensitive(state->entry_domain, TRUE);
+ }
+ gtk_editable_set_editable(GTK_EDITABLE(state->entry_domain), TRUE);
+ gtk_box_pack_start(GTK_BOX(vbox), state->entry_domain, TRUE, TRUE, 0);
+ gtk_widget_show(state->entry_domain);
+ }
+ gtk_widget_show(button_domain);
+
+ /* WORKGROUP */
+ group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button_domain));
+ button_workgroup = gtk_radio_button_new_with_label(group, "Workgroup");
+ if (state->name_type_initial == NetSetupWorkgroupName) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_workgroup), TRUE);
+ }
+ gtk_box_pack_start(GTK_BOX(vbox), button_workgroup, TRUE, TRUE, 0);
+ g_signal_connect(G_OBJECT(button_workgroup), "clicked",
+ G_CALLBACK(callback_do_join_workgroup),
+ (gpointer)state);
+ {
+ gtk_entry_set_max_length(GTK_ENTRY(state->entry_workgroup),
+ MAX_NETBIOS_NAME_LEN);
+ g_signal_connect(G_OBJECT(state->entry_workgroup), "changed",
+ G_CALLBACK(callback_enter_workgroup_and_unlock),
+ (gpointer)state);
+ g_signal_connect(G_OBJECT(state->entry_workgroup), "activate",
+ G_CALLBACK(callback_continue),
+ (gpointer)state);
+
+ if (state->name_type_initial == NetSetupWorkgroupName) {
+ gtk_entry_set_text(GTK_ENTRY(state->entry_workgroup),
+ state->name_buffer_initial);
+ gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
+ }
+ gtk_box_pack_start(GTK_BOX(vbox), state->entry_workgroup, TRUE, TRUE, 0);
+ gtk_widget_show(state->entry_workgroup);
+ }
+ gtk_widget_show(button_workgroup);
+
+ /* Advanced Options */
+ frame_horz = gtk_frame_new("Advanced Options");
+ gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
+ gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
+
+ /* OUs */
+ gtk_container_add(GTK_CONTAINER(vbox), state->button_get_ous);
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), FALSE);
+ g_signal_connect(G_OBJECT(state->button_get_ous), "clicked",
+ G_CALLBACK(callback_do_getous),
+ (gpointer)state);
+
+ state->entry_ou_list = gtk_combo_box_entry_new_text();
+ gtk_widget_set_sensitive(state->entry_ou_list, FALSE);
+ if (state->name_type_initial == NetSetupWorkgroupName) {
+ gtk_widget_set_sensitive(state->entry_ou_list, FALSE);
+ gtk_widget_set_sensitive(state->button_get_ous, FALSE);
+ }
+ gtk_box_pack_start(GTK_BOX(vbox), state->entry_ou_list, TRUE, TRUE, 0);
+ gtk_widget_show(state->entry_ou_list);
+
+ {
+ state->label_winbind = gtk_check_button_new_with_label("Modify winbind configuration");
+ gtk_box_pack_start(GTK_BOX(vbox), state->label_winbind, TRUE, TRUE, 0);
+ gtk_widget_set_sensitive(state->label_winbind, FALSE);
+ }
+
+
+ /* BUTTONS */
+ bbox = gtk_hbutton_box_new();
+ gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
+ gtk_container_add(GTK_CONTAINER(box1), bbox);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
+ gtk_box_set_spacing(GTK_BOX(bbox), 10);
+
+ state->window_do_change = window;
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+ gtk_container_add(GTK_CONTAINER(bbox), state->button_ok);
+ g_signal_connect(G_OBJECT(state->button_ok), "clicked",
+ G_CALLBACK(callback_do_join),
+ (gpointer)state);
+
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ gtk_container_add(GTK_CONTAINER(bbox), button);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(callback_do_freeauth_and_close),
+ (gpointer)state);
+
+ gtk_widget_show_all(window);
+}
+
+static void callback_do_about(GtkWidget *widget,
+ gpointer data)
+{
+ GdkPixbuf *logo;
+ GError *error = NULL;
+ GtkWidget *about;
+
+ struct join_state *state = (struct join_state *)data;
+
+ debug("callback_do_about called\n");
+
+ logo = gdk_pixbuf_new_from_file(SAMBA_IMAGE_PATH,
+ &error);
+ if (logo == NULL) {
+ g_print("failed to load logo from %s: %s\n",
+ SAMBA_IMAGE_PATH, error->message);
+ }
+
+ about = gtk_about_dialog_new();
+ gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(about), "Samba");
+ gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about), "3.2.0pre3");
+ gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about),
+ "Copyright Andrew Tridgell and the Samba Team 1992-2008\n"
+ "Copyright Günther Deschner 2007-2008");
+ gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about), "GPLv3");
+ gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about), "http://www.samba.org");
+ gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(about), "http://www.samba.org");
+ if (logo) {
+ gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), logo);
+ }
+ gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about), "Samba gtk domain join utility");
+ gtk_window_set_modal(GTK_WINDOW(about), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(about), GTK_WINDOW(state->window_main));
+ g_signal_connect_swapped(about, "response",
+ G_CALLBACK(gtk_widget_destroy),
+ about);
+
+ gtk_widget_show(about);
+}
+
+static int draw_main_window(struct join_state *state)
+{
+ GtkWidget *window;
+ GtkWidget *button;
+ GtkWidget *label;
+ GtkWidget *main_vbox;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *bbox;
+ GtkWidget *image;
+ GtkWidget *table;
+ GtkWidget *entry;
+ GdkPixbuf *icon;
+ GError *error = NULL;
+
+ icon = gdk_pixbuf_new_from_file(SAMBA_ICON_PATH,
+ &error);
+ if (icon == NULL) {
+ g_print("failed to load icon from %s : %s\n",
+ SAMBA_ICON_PATH, error->message);
+ }
+
+#if 1
+ image = gtk_image_new_from_file(SAMBA_IMAGE_PATH_SMALL);
+#else
+ image = gtk_image_new_from_file("/usr/share/pixmaps/redhat-system_settings.png");
+#endif
+ if (image == NULL) {
+ g_print("failed to load logo from %s : %s\n",
+ SAMBA_IMAGE_PATH_SMALL, error->message);
+ }
+
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ state->window_main = window;
+
+ gtk_window_set_title(GTK_WINDOW(window), "Samba - Join Domain dialogue");
+ gtk_widget_set_size_request(GTK_WIDGET(window), 600, 600);
+ gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
+ gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
+ gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
+
+ g_signal_connect(G_OBJECT(window), "delete_event",
+ G_CALLBACK(callback_delete_event), NULL);
+
+ gtk_container_set_border_width(GTK_CONTAINER(window), 10);
+
+ main_vbox = gtk_vbox_new(FALSE, 10);
+ gtk_container_add(GTK_CONTAINER(window), main_vbox);
+
+#if 0
+ gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10);
+ gtk_widget_show(image);
+#endif
+ /* Hbox */
+ hbox = gtk_hbox_new(FALSE, 10);
+ gtk_container_add(GTK_CONTAINER(main_vbox), hbox);
+
+ {
+/* gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10); */
+/* gtk_misc_set_alignment(GTK_MISC(image), 0, 0); */
+ gtk_widget_set_size_request(GTK_WIDGET(image), 150, 40);
+ gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 10);
+ gtk_widget_show(image);
+
+ /* Label */
+ label = gtk_label_new("Samba uses the following information to identify your computer on the network.");
+/* gtk_misc_set_alignment(GTK_MISC(label), 0, 0); */
+ gtk_widget_set_size_request(GTK_WIDGET(label), 400, 40);
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+ }
+
+ gtk_widget_show(hbox);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
+ gtk_container_add(GTK_CONTAINER(main_vbox), vbox);
+
+ /* Table */
+ table = gtk_table_new(6, 3, TRUE);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 5);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 5);
+ gtk_container_add(GTK_CONTAINER(vbox), table);
+
+ {
+ /* Label */
+ label = gtk_label_new("Computer description:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
+ gtk_widget_show(label);
+
+ state->button_apply = gtk_button_new_from_stock(GTK_STOCK_APPLY);
+
+ /* Entry */
+ entry = gtk_entry_new();
+ gtk_entry_set_max_length(GTK_ENTRY(entry), 256);
+
+ if (!state->target_hostname && state->uid != 0) {
+ gtk_widget_set_sensitive(GTK_WIDGET(entry), FALSE);
+ }
+ g_signal_connect(G_OBJECT(entry), "changed",
+ G_CALLBACK(callback_enter_computer_description_and_unlock),
+ state);
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(callback_apply_continue),
+ (gpointer)state);
+
+ gtk_entry_set_text(GTK_ENTRY(entry), (char *)state->comment);
+ gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
+ gtk_table_attach_defaults(GTK_TABLE(table), entry, 1, 3, 0, 1);
+ gtk_widget_show(entry);
+ }
+
+ /* Label */
+ label = gtk_label_new("For example: \"Samba \%v\".");
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 1, 2);
+ gtk_widget_show(label);
+
+ /* Label */
+ label = gtk_label_new("Full computer name:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
+ gtk_widget_show(label);
+
+ {
+ /* Label */
+ char *str = NULL;
+ if (state->name_type_initial == NetSetupDomainName) {
+ if (asprintf(&str, "%s.%s", state->my_hostname,
+ state->my_dnsdomain) == -1) {
+ return -1;
+ }
+ } else {
+ if (asprintf(&str, "%s.", state->my_hostname) == -1) {
+ return -1;
+ }
+ }
+
+ label = gtk_label_new(str);
+ SAFE_FREE(str);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 2, 3);
+ gtk_widget_show(label);
+ }
+
+ /* Label */
+ if (state->name_type_initial == NetSetupDomainName) {
+ label = gtk_label_new("Domain:");
+ } else {
+ label = gtk_label_new("Workgroup:");
+ }
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
+ gtk_widget_show(label);
+ state->label_current_name_type = label;
+
+ /* Label */
+ label = gtk_label_new(state->name_buffer_initial);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 3, 4);
+ gtk_widget_show(label);
+ state->label_current_name_buffer = label;
+
+ {
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(vbox), hbox);
+ label = gtk_label_new("To rename this computer or join a domain, click Change.");
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+
+ }
+
+ /* bbox */
+ bbox = gtk_hbutton_box_new();
+ gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
+ gtk_container_add(GTK_CONTAINER(hbox), bbox);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
+ gtk_box_set_spacing(GTK_BOX(bbox), 10);
+
+ button = gtk_button_new_with_mnemonic("Ch_ange");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(callback_do_change),
+ (gpointer)state);
+ gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
+ if (!state->target_hostname && state->uid != 0) {
+ gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
+ }
+ gtk_widget_show(button);
+
+ /* Label (hidden) */
+ state->label_reboot = gtk_label_new(NULL);
+ gtk_label_set_line_wrap(GTK_LABEL(state->label_reboot), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(state->label_reboot), 0, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), state->label_reboot, TRUE, TRUE, 0);
+ if (!state->target_hostname && state->uid != 0) {
+ gtk_label_set_text(GTK_LABEL(state->label_reboot),
+ "You cannot change computer description as you're not running with root permissions");
+ }
+
+ gtk_widget_show(state->label_reboot);
+
+#if 0
+ gtk_box_pack_start(GTK_BOX(vbox),
+ create_bbox(window, TRUE, NULL, 10, 85, 20, GTK_BUTTONBOX_END),
+ TRUE, TRUE, 5);
+#endif
+ {
+
+ GtkWidget *frame;
+ GtkWidget *bbox2;
+ GtkWidget *button2;
+
+ frame = gtk_frame_new(NULL);
+ bbox2 = gtk_hbutton_box_new();
+
+ gtk_container_set_border_width(GTK_CONTAINER(bbox2), 5);
+ gtk_container_add(GTK_CONTAINER(frame), bbox2);
+
+ /* Set the appearance of the Button Box */
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox2), GTK_BUTTONBOX_END);
+ gtk_box_set_spacing(GTK_BOX(bbox2), 10);
+ /*gtk_button_box_set_child_size(GTK_BUTTON_BOX(bbox2), child_w, child_h);*/
+
+ button2 = gtk_button_new_from_stock(GTK_STOCK_OK);
+ gtk_container_add(GTK_CONTAINER(bbox2), button2);
+ g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(callback_do_exit), state);
+
+ button2 = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ gtk_container_add(GTK_CONTAINER(bbox2), button2);
+ g_signal_connect(G_OBJECT(button2), "clicked",
+ G_CALLBACK(callback_delete_event),
+ window);
+
+ gtk_container_add(GTK_CONTAINER(bbox2), state->button_apply);
+ g_signal_connect(G_OBJECT(state->button_apply), "clicked",
+ G_CALLBACK(callback_apply_description_change),
+ state);
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
+
+ button2 = gtk_button_new_from_stock(GTK_STOCK_ABOUT);
+ gtk_container_add(GTK_CONTAINER(bbox2), button2);
+ g_signal_connect(G_OBJECT(button2), "clicked",
+ G_CALLBACK(callback_do_about),
+ state);
+#if 0
+ button2 = gtk_button_new_from_stock(GTK_STOCK_HELP);
+ gtk_container_add(GTK_CONTAINER(bbox2), button2);
+ g_signal_connect(G_OBJECT(button2), "clicked",
+ G_CALLBACK(callback_do_about),
+ window);
+#endif
+ gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 5);
+ }
+
+ gtk_widget_show_all(window);
+
+ return 0;
+}
+
+static int init_join_state(struct join_state **state)
+{
+ struct join_state *s;
+
+ s = (struct join_state *)malloc(sizeof(struct join_state));
+ if (!s) {
+ return -1;
+ }
+
+ memset(s, '\0', sizeof(struct join_state));
+
+ *state = s;
+
+ return 0;
+}
+
+static NET_API_STATUS get_server_properties(struct join_state *state)
+{
+ struct SERVER_INFO_101 *info101 = NULL;
+ struct SERVER_INFO_1005 *info1005 = NULL;
+ NET_API_STATUS status;
+
+ status = NetServerGetInfo(state->target_hostname,
+ 101,
+ (uint8_t **)&info101);
+ if (status == 0) {
+ state->comment = strdup(info101->sv101_comment);
+ if (!state->comment) {
+ return -1;
+ }
+ SAFE_FREE(state->my_hostname);
+ state->my_hostname = strdup(info101->sv101_name);
+ if (!state->my_hostname) {
+ return -1;
+ }
+ NetApiBufferFree(info101);
+ return NET_API_STATUS_SUCCESS;
+ }
+
+ switch (status) {
+ case 124: /* WERR_INVALID_LEVEL */
+ case 50: /* WERR_NOT_SUPPORTED */
+ break;
+ default:
+ goto failed;
+ }
+
+ status = NetServerGetInfo(state->target_hostname,
+ 1005,
+ (uint8_t **)&info1005);
+ if (status == 0) {
+ state->comment = strdup(info1005->sv1005_comment);
+ if (!state->comment) {
+ return -1;
+ }
+ NetApiBufferFree(info1005);
+ return NET_API_STATUS_SUCCESS;
+ }
+
+ failed:
+ printf("NetServerGetInfo failed with: %s\n",
+ libnetapi_get_error_string(state->ctx, status));
+
+ return status;
+}
+
+static int initialize_join_state(struct join_state *state,
+ const char *debug_level,
+ const char *target_hostname,
+ const char *target_username)
+{
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status = 0;
+
+ status = libnetapi_init(&ctx);
+ if (status) {
+ return status;
+ }
+
+ if (debug_level) {
+ libnetapi_set_debuglevel(ctx, debug_level);
+ }
+
+ if (target_hostname) {
+ state->target_hostname = strdup(target_hostname);
+ if (!state->target_hostname) {
+ return -1;
+ }
+ }
+
+ if (target_username) {
+ char *puser = strdup(target_username);
+ char *p = NULL;
+
+ if ((p = strchr(puser,'%'))) {
+ size_t len;
+ *p = 0;
+ libnetapi_set_username(ctx, puser);
+ libnetapi_set_password(ctx, p+1);
+ len = strlen(p+1);
+ memset(strchr(target_username,'%')+1,'X',len);
+ } else {
+ libnetapi_set_username(ctx, puser);
+ }
+ free(puser);
+ }
+
+ {
+ char my_hostname[HOST_NAME_MAX];
+ const char *p = NULL;
+ struct hostent *hp = NULL;
+
+ if (gethostname(my_hostname, sizeof(my_hostname)) == -1) {
+ return -1;
+ }
+
+ p = strchr(my_hostname, '.');
+ if (p) {
+ my_hostname[strlen(my_hostname)-strlen(p)] = '\0';
+ }
+ state->my_hostname = strdup(my_hostname);
+ if (!state->my_hostname) {
+ return -1;
+ }
+ debug("state->my_hostname: %s\n", state->my_hostname);
+
+ hp = gethostbyname(my_hostname);
+ if (!hp || !hp->h_name || !*hp->h_name) {
+ return -1;
+ }
+
+ state->my_fqdn = strdup(hp->h_name);
+ if (!state->my_fqdn) {
+ return -1;
+ }
+ debug("state->my_fqdn: %s\n", state->my_fqdn);
+
+ p = strchr(state->my_fqdn, '.');
+ if (p) {
+ p++;
+ state->my_dnsdomain = strdup(p);
+ } else {
+ state->my_dnsdomain = strdup("");
+ }
+ if (!state->my_dnsdomain) {
+ return -1;
+ }
+ debug("state->my_dnsdomain: %s\n", state->my_dnsdomain);
+ }
+
+ {
+ const char *buffer = NULL;
+ uint16_t type = 0;
+ status = NetGetJoinInformation(state->target_hostname,
+ &buffer,
+ &type);
+ if (status != 0) {
+ printf("NetGetJoinInformation failed with: %s\n",
+ libnetapi_get_error_string(state->ctx, status));
+ return status;
+ }
+ debug("NetGetJoinInformation gave: %s and %d\n", buffer, type);
+ state->name_buffer_initial = strdup(buffer);
+ if (!state->name_buffer_initial) {
+ return -1;
+ }
+ state->name_type_initial = type;
+ NetApiBufferFree((void *)buffer);
+ }
+
+ status = get_server_properties(state);
+ if (status != 0) {
+ return -1;
+ }
+
+ state->uid = geteuid();
+
+ state->ctx = ctx;
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ GOptionContext *context = NULL;
+ static const char *debug_level = NULL;
+ static const char *target_hostname = NULL;
+ static const char *target_username = NULL;
+ struct join_state *state = NULL;
+ GError *error = NULL;
+ int ret = 0;
+
+ static GOptionEntry entries[] = {
+ { "debug", 'd', 0, G_OPTION_ARG_STRING, &debug_level, "Debug level (for samba)", "N" },
+ { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output", 0 },
+ { "target", 'S', 0, G_OPTION_ARG_STRING, &target_hostname, "Target hostname", 0 },
+ { "username", 'U', 0, G_OPTION_ARG_STRING, &target_username, "Target hostname", 0 },
+ { NULL }
+ };
+
+ context = g_option_context_new("- Samba domain join utility");
+ g_option_context_add_main_entries(context, entries, NULL);
+/* g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE); */
+ g_option_context_add_group(context, gtk_get_option_group(TRUE));
+ g_option_context_parse(context, &argc, &argv, &error);
+
+ gtk_init(&argc, &argv);
+ g_set_application_name("Samba");
+
+ ret = init_join_state(&state);
+ if (ret) {
+ return ret;
+ }
+
+ ret = initialize_join_state(state, debug_level,
+ target_hostname,
+ target_username);
+ if (ret) {
+ return ret;
+ }
+
+ draw_main_window(state);
+
+ gtk_main();
+
+ do_cleanup(state);
+
+ return 0;
+}
diff --git a/source3/lib/netapi/examples/netdomjoin-gui/samba.ico b/source3/lib/netapi/examples/netdomjoin-gui/samba.ico
new file mode 100755
index 0000000..b70c959
--- /dev/null
+++ b/source3/lib/netapi/examples/netdomjoin-gui/samba.ico
Binary files differ
diff --git a/source3/lib/netapi/examples/netlogon/netlogon_control.c b/source3/lib/netapi/examples/netlogon/netlogon_control.c
new file mode 100644
index 0000000..34361cd
--- /dev/null
+++ b/source3/lib/netapi/examples/netlogon/netlogon_control.c
@@ -0,0 +1,143 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * I_NetLogonControl query
+ * Copyright (C) Guenther Deschner 2009
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint32_t function_code = NETLOGON_CONTROL_QUERY;
+ uint32_t level = 1;
+ uint8_t *buffer = NULL;
+ struct NETLOGON_INFO_1 *i1 = NULL;
+ struct NETLOGON_INFO_2 *i2 = NULL;
+ struct NETLOGON_INFO_3 *i3 = NULL;
+ struct NETLOGON_INFO_4 *i4 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("netlogon_control", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ function_code = atoi(poptGetArg(pc));
+ }
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* I_NetLogonControl */
+
+ status = I_NetLogonControl(hostname,
+ function_code,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("I_NetLogonControl failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ if (!buffer) {
+ goto out;
+ }
+
+ switch (level) {
+ case 1:
+ i1 = (struct NETLOGON_INFO_1 *)buffer;
+
+ printf("Flags: %x\n", i1->netlog1_flags);
+ printf("Connection Status Status = %d 0x%x %s\n",
+ i1->netlog1_pdc_connection_status,
+ i1->netlog1_pdc_connection_status,
+ libnetapi_errstr(i1->netlog1_pdc_connection_status));
+
+ break;
+ case 2:
+ i2 = (struct NETLOGON_INFO_2 *)buffer;
+
+ printf("Flags: %x\n", i2->netlog2_flags);
+ printf("Trusted DC Name %s\n", i2->netlog2_trusted_dc_name);
+ printf("Trusted DC Connection Status Status = %d 0x%x %s\n",
+ i2->netlog2_tc_connection_status,
+ i2->netlog2_tc_connection_status,
+ libnetapi_errstr(i2->netlog2_tc_connection_status));
+ printf("Trust Verification Status Status = %d 0x%x %s\n",
+ i2->netlog2_pdc_connection_status,
+ i2->netlog2_pdc_connection_status,
+ libnetapi_errstr(i2->netlog2_pdc_connection_status));
+
+ break;
+ case 3:
+ i3 = (struct NETLOGON_INFO_3 *)buffer;
+
+ printf("Flags: %x\n", i3->netlog1_flags);
+ printf("Logon Attempts: %d\n", i3->netlog3_logon_attempts);
+
+ break;
+ case 4:
+ i4 = (struct NETLOGON_INFO_4 *)buffer;
+
+ printf("Trusted DC Name %s\n", i4->netlog4_trusted_dc_name);
+ printf("Trusted Domain Name %s\n", i4->netlog4_trusted_domain_name);
+
+ break;
+ default:
+ break;
+ }
+
+ out:
+ NetApiBufferFree(buffer);
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/netlogon/netlogon_control2.c b/source3/lib/netapi/examples/netlogon/netlogon_control2.c
new file mode 100644
index 0000000..72315c9
--- /dev/null
+++ b/source3/lib/netapi/examples/netlogon/netlogon_control2.c
@@ -0,0 +1,147 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * I_NetLogonControl2 query
+ * Copyright (C) Guenther Deschner 2009
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint32_t function_code = NETLOGON_CONTROL_QUERY;
+ uint32_t level = 1;
+ uint8_t *buffer = NULL;
+ struct NETLOGON_INFO_1 *i1 = NULL;
+ struct NETLOGON_INFO_2 *i2 = NULL;
+ struct NETLOGON_INFO_3 *i3 = NULL;
+ struct NETLOGON_INFO_4 *i4 = NULL;
+ char *domain = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("netlogon_control", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ function_code = atoi(poptGetArg(pc));
+ }
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ domain = strdup("TEST");
+
+ /* I_NetLogonControl2 */
+
+ status = I_NetLogonControl2(hostname,
+ function_code,
+ level,
+ (uint8_t *)domain,
+ &buffer);
+ if (status != 0) {
+ printf("I_NetLogonControl2 failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ if (!buffer) {
+ goto out;
+ }
+
+ switch (level) {
+ case 1:
+ i1 = (struct NETLOGON_INFO_1 *)buffer;
+
+ printf("Flags: %x\n", i1->netlog1_flags);
+ printf("Connection Status Status = %d 0x%x %s\n",
+ i1->netlog1_pdc_connection_status,
+ i1->netlog1_pdc_connection_status,
+ libnetapi_errstr(i1->netlog1_pdc_connection_status));
+
+ break;
+ case 2:
+ i2 = (struct NETLOGON_INFO_2 *)buffer;
+
+ printf("Flags: %x\n", i2->netlog2_flags);
+ printf("Trusted DC Name %s\n", i2->netlog2_trusted_dc_name);
+ printf("Trusted DC Connection Status Status = %d 0x%x %s\n",
+ i2->netlog2_tc_connection_status,
+ i2->netlog2_tc_connection_status,
+ libnetapi_errstr(i2->netlog2_tc_connection_status));
+ printf("Trust Verification Status Status = %d 0x%x %s\n",
+ i2->netlog2_pdc_connection_status,
+ i2->netlog2_pdc_connection_status,
+ libnetapi_errstr(i2->netlog2_pdc_connection_status));
+
+ break;
+ case 3:
+ i3 = (struct NETLOGON_INFO_3 *)buffer;
+
+ printf("Flags: %x\n", i3->netlog1_flags);
+ printf("Logon Attempts: %d\n", i3->netlog3_logon_attempts);
+
+ break;
+ case 4:
+ i4 = (struct NETLOGON_INFO_4 *)buffer;
+
+ printf("Trusted DC Name %s\n", i4->netlog4_trusted_dc_name);
+ printf("Trusted Domain Name %s\n", i4->netlog4_trusted_domain_name);
+
+ break;
+ default:
+ break;
+ }
+
+ out:
+ NetApiBufferFree(buffer);
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/netlogon/nltest.c b/source3/lib/netapi/examples/netlogon/nltest.c
new file mode 100644
index 0000000..2dd368f
--- /dev/null
+++ b/source3/lib/netapi/examples/netlogon/nltest.c
@@ -0,0 +1,677 @@
+/*
+ * Samba Unix/Linux SMB client library
+ * Distributed SMB/CIFS Server Management Utility
+ * Nltest netlogon testing tool
+ *
+ * Copyright (C) Guenther Deschner 2009
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+enum {
+ OPT_SERVER = 1,
+ OPT_DBFLAG,
+ OPT_SC_QUERY,
+ OPT_SC_RESET,
+ OPT_SC_VERIFY,
+ OPT_SC_CHANGE_PWD,
+ OPT_DSGETDC,
+ OPT_PDC,
+ OPT_DS,
+ OPT_DSP,
+ OPT_GC,
+ OPT_KDC,
+ OPT_TIMESERV,
+ OPT_GTIMESERV,
+ OPT_WS,
+ OPT_NETBIOS,
+ OPT_DNS,
+ OPT_IP,
+ OPT_FORCE,
+ OPT_WRITABLE,
+ OPT_AVOIDSELF,
+ OPT_LDAPONLY,
+ OPT_BACKG,
+ OPT_DS_6,
+ OPT_TRY_NEXT_CLOSEST_SITE,
+ OPT_SITE,
+ OPT_ACCOUNT,
+ OPT_RET_DNS,
+ OPT_RET_NETBIOS,
+ OPT_DSREGDNS
+};
+
+/****************************************************************
+****************************************************************/
+
+static void print_netlogon_info_result(uint32_t level,
+ uint8_t *buffer)
+{
+ struct NETLOGON_INFO_1 *i1 = NULL;
+ struct NETLOGON_INFO_2 *i2 = NULL;
+ struct NETLOGON_INFO_3 *i3 = NULL;
+ struct NETLOGON_INFO_4 *i4 = NULL;
+
+ if (!buffer) {
+ return;
+ }
+
+ switch (level) {
+ case 1:
+ i1 = (struct NETLOGON_INFO_1 *)buffer;
+
+ printf("Flags: %x\n", i1->netlog1_flags);
+ printf("Connection Status Status = %d 0x%x %s\n",
+ i1->netlog1_pdc_connection_status,
+ i1->netlog1_pdc_connection_status,
+ libnetapi_errstr(i1->netlog1_pdc_connection_status));
+
+ break;
+ case 2:
+ i2 = (struct NETLOGON_INFO_2 *)buffer;
+
+ printf("Flags: %x\n", i2->netlog2_flags);
+ printf("Trusted DC Name %s\n", i2->netlog2_trusted_dc_name);
+ printf("Trusted DC Connection Status Status = %d 0x%x %s\n",
+ i2->netlog2_tc_connection_status,
+ i2->netlog2_tc_connection_status,
+ libnetapi_errstr(i2->netlog2_tc_connection_status));
+ printf("Trust Verification Status Status = %d 0x%x %s\n",
+ i2->netlog2_pdc_connection_status,
+ i2->netlog2_pdc_connection_status,
+ libnetapi_errstr(i2->netlog2_pdc_connection_status));
+
+ break;
+ case 3:
+ i3 = (struct NETLOGON_INFO_3 *)buffer;
+
+ printf("Flags: %x\n", i3->netlog1_flags);
+ printf("Logon Attempts: %d\n", i3->netlog3_logon_attempts);
+
+ break;
+ case 4:
+ i4 = (struct NETLOGON_INFO_4 *)buffer;
+
+ printf("Trusted DC Name %s\n", i4->netlog4_trusted_dc_name);
+ printf("Trusted Domain Name %s\n", i4->netlog4_trusted_domain_name);
+
+ break;
+ default:
+ break;
+ }
+}
+
+/****************************************************************
+****************************************************************/
+
+static void print_dc_info_flags(uint32_t flags)
+{
+ if (flags & DS_PDC_FLAG)
+ printf("PDC ");
+ if (flags & DS_GC_FLAG)
+ printf("GC ");
+ if (flags & DS_DS_FLAG)
+ printf("DS ");
+ if (flags & DS_LDAP_FLAG)
+ printf("LDAP ");
+ if (flags & DS_KDC_FLAG)
+ printf("KDC ");
+ if (flags & DS_TIMESERV_FLAG)
+ printf("TIMESERV ");
+ if (flags & DS_GOOD_TIMESERV_FLAG)
+ printf("GTIMESERV ");
+ if (flags & DS_WRITABLE_FLAG)
+ printf("WRITABLE ");
+ if (flags & DS_DNS_FOREST_FLAG)
+ printf("DNS_FOREST ");
+ if (flags & DS_CLOSEST_FLAG)
+ printf("CLOSE_SITE ");
+ if (flags & DS_FULL_SECRET_DOMAIN_6_FLAG)
+ printf("FULL_SECRET ");
+ if (flags & DS_WS_FLAG)
+ printf("WS ");
+ if (flags & DS_DS_8_FLAG)
+ printf("DS_8 ");
+ printf("\n");
+}
+
+/****************************************************************
+****************************************************************/
+
+static void print_dc_info(struct DOMAIN_CONTROLLER_INFO *dc_info)
+{
+ if (dc_info->flags) {
+ printf(" DC: %s\n", dc_info->domain_controller_name);
+ printf(" Address: %s\n", dc_info->domain_controller_address);
+/* printf(" Dom Guid: %s\n", X(domain_guid)); */
+ printf(" Dom Name: %s\n", dc_info->domain_name);
+ printf(" Forest Name: %s\n", dc_info->dns_forest_name);
+ printf(" Dc Site Name: %s\n", dc_info->dc_site_name);
+ printf("Our Site Name: %s\n", dc_info->client_site_name);
+ printf(" Flags: ");
+ print_dc_info_flags(dc_info->flags);
+ } else {
+ printf(" DC: %s\n", dc_info->domain_controller_name);
+ printf(" Address: %s\n", dc_info->domain_controller_address);
+ printf(" Dom Name: %s\n", dc_info->domain_name);
+ }
+}
+
+/****************************************************************
+****************************************************************/
+
+int main(int argc, const char **argv)
+{
+ int opt;
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ char *opt_server = NULL;
+ char *opt_domain = NULL;
+ int opt_dbflag = 0;
+ int opt_pdc = 0;
+ int opt_ds = 0;
+ int opt_dsp = 0;
+ int opt_gc = 0;
+ int opt_kdc = 0;
+ int opt_timeserv = 0;
+ int opt_gtimeserv = 0;
+ int opt_ws = 0;
+ int opt_netbios = 0;
+ int opt_dns = 0;
+ int opt_ip = 0;
+ int opt_force = 0;
+ int opt_writable = 0;
+ int opt_avoidself = 0;
+ int opt_ldaponly = 0;
+ int opt_backg = 0;
+ int opt_ds_6 = 0;
+ int opt_try_next_closest_site = 0;
+ char *opt_site = NULL;
+ char *opt_account = NULL;
+ int opt_ret_dns = 0;
+ int opt_ret_netbios = 0;
+ int opt_dsregdns = 0;
+ uint32_t query_level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t flags = 0;
+ struct DOMAIN_CONTROLLER_INFO *dc_info = NULL;
+
+ poptContext pc;
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ {
+ .longName = "server",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_server,
+ .val = OPT_SERVER,
+ .descrip = "Servername",
+ .argDescrip = "SERVER",
+ },
+ {
+ .longName = "dbflag",
+ .shortName = 0,
+ .argInfo = POPT_ARG_INT,
+ .arg = &opt_dbflag,
+ .val = OPT_DBFLAG,
+ .descrip = "New Debug Flag",
+ .argDescrip = "HEXFLAGS",
+ },
+ {
+ .longName = "sc_query",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_domain,
+ .val = OPT_SC_QUERY,
+ .descrip = "Query secure channel for domain on server",
+ .argDescrip = "DOMAIN",
+ },
+ {
+ .longName = "sc_reset",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_domain,
+ .val = OPT_SC_RESET,
+ .descrip = "Reset secure channel for domain on server to dcname",
+ .argDescrip = "DOMAIN",
+ },
+ {
+ .longName = "sc_verify",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_domain,
+ .val = OPT_SC_VERIFY,
+ .descrip = "Verify secure channel for domain on server",
+ .argDescrip = "DOMAIN",
+ },
+ {
+ .longName = "sc_change_pwd",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_domain,
+ .val = OPT_SC_CHANGE_PWD,
+ .descrip = "Change a secure channel password for domain on server",
+ .argDescrip = "DOMAIN",
+ },
+ {
+ .longName = "dsgetdc",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_domain,
+ .val = OPT_DSGETDC,
+ .descrip = "Call DsGetDcName",
+ .argDescrip = "DOMAIN",
+ },
+ {
+ .longName = "pdc",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_pdc,
+ .val = OPT_PDC,
+ .descrip = NULL,
+ },
+ {
+ .longName = "ds",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_ds,
+ .val = OPT_DS,
+ .descrip = NULL,
+ },
+ {
+ .longName = "dsp",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_dsp,
+ .val = OPT_DSP,
+ .descrip = NULL,
+ },
+ {
+ .longName = "gc",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_gc,
+ .val = OPT_GC,
+ .descrip = NULL,
+ },
+ {
+ .longName = "kdc",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_kdc,
+ .val = OPT_KDC,
+ .descrip = NULL,
+ },
+ {
+ .longName = "timeserv",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_timeserv,
+ .val = OPT_TIMESERV,
+ .descrip = NULL,
+ },
+ {
+ .longName = "gtimeserv",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_gtimeserv,
+ .val = OPT_GTIMESERV,
+ .descrip = NULL,
+ },
+ {
+ .longName = "ws",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_ws,
+ .val = OPT_WS,
+ .descrip = NULL,
+ },
+ {
+ .longName = "netbios",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_netbios,
+ .val = OPT_NETBIOS,
+ .descrip = NULL,
+ },
+ {
+ .longName = "dns",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_dns,
+ .val = OPT_DNS,
+ .descrip = NULL,
+ },
+ {
+ .longName = "ip",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_ip,
+ .val = OPT_IP,
+ .descrip = NULL,
+ },
+ {
+ .longName = "force",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_force,
+ .val = OPT_FORCE,
+ .descrip = NULL,
+ },
+ {
+ .longName = "writable",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_writable,
+ .val = OPT_WRITABLE,
+ .descrip = NULL,
+ },
+ {
+ .longName = "avoidself",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_avoidself,
+ .val = OPT_AVOIDSELF,
+ .descrip = NULL,
+ },
+ {
+ .longName = "ldaponly",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_ldaponly,
+ .val = OPT_LDAPONLY,
+ .descrip = NULL,
+ },
+ {
+ .longName = "backg",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_backg,
+ .val = OPT_BACKG,
+ .descrip = NULL,
+ },
+ {
+ .longName = "ds_6",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_ds_6,
+ .val = OPT_DS_6,
+ .descrip = NULL,
+ },
+ {
+ .longName = "try_next_closest_site",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_try_next_closest_site,
+ .val = OPT_TRY_NEXT_CLOSEST_SITE,
+ .descrip = NULL,
+ },
+ {
+ .longName = "site",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_site,
+ .val = OPT_SITE,
+ .descrip = "SITE",
+ },
+ {
+ .longName = "account",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_account,
+ .val = OPT_ACCOUNT,
+ .descrip = "ACCOUNT",
+ },
+ {
+ .longName = "ret_dns",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_ret_dns,
+ .val = OPT_RET_DNS,
+ .descrip = NULL,
+ },
+ {
+ .longName = "ret_netbios",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_ret_netbios,
+ .val = OPT_RET_NETBIOS,
+ .descrip = NULL,
+ },
+ {
+ .longName = "dsregdns",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_dsregdns,
+ .val = OPT_DSREGDNS,
+ .descrip = "Force registration of all DC-specific DNS records",
+ },
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("nltest", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "<options>");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (argc == 1) {
+ poptPrintHelp(pc, stderr, 0);
+ goto done;
+ }
+
+ poptResetContext(pc);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+
+ case OPT_SERVER:
+
+ if ((opt_server[0] == '/' && opt_server[1] == '/') ||
+ (opt_server[0] == '\\' && opt_server[1] == '\\')) {
+ opt_server += 2;
+ }
+
+ break;
+
+ case OPT_DBFLAG:
+ query_level = 1;
+ status = I_NetLogonControl2(opt_server,
+ NETLOGON_CONTROL_SET_DBFLAG,
+ query_level,
+ (uint8_t *)&opt_dbflag,
+ &buffer);
+ if (status != 0) {
+ fprintf(stderr, "I_NetlogonControl failed: Status = %d 0x%x %s\n",
+ status, status,
+ libnetapi_get_error_string(ctx, status));
+ goto done;
+ }
+
+ print_netlogon_info_result(query_level, buffer);
+
+ break;
+ case OPT_SC_QUERY:
+ query_level = 2;
+ status = I_NetLogonControl2(opt_server,
+ NETLOGON_CONTROL_TC_QUERY,
+ query_level,
+ (uint8_t *)opt_domain,
+ &buffer);
+ if (status != 0) {
+ fprintf(stderr, "I_NetlogonControl failed: Status = %d 0x%x %s\n",
+ status, status,
+ libnetapi_get_error_string(ctx, status));
+ goto done;
+ }
+
+ print_netlogon_info_result(query_level, buffer);
+
+ break;
+ case OPT_SC_VERIFY:
+ query_level = 2;
+ status = I_NetLogonControl2(opt_server,
+ NETLOGON_CONTROL_TC_VERIFY,
+ query_level,
+ (uint8_t *)opt_domain,
+ &buffer);
+ if (status != 0) {
+ fprintf(stderr, "I_NetlogonControl failed: Status = %d 0x%x %s\n",
+ status, status,
+ libnetapi_get_error_string(ctx, status));
+ goto done;
+ }
+
+ print_netlogon_info_result(query_level, buffer);
+
+ break;
+ case OPT_SC_RESET:
+ query_level = 2;
+ status = I_NetLogonControl2(opt_server,
+ NETLOGON_CONTROL_REDISCOVER,
+ query_level,
+ (uint8_t *)opt_domain,
+ &buffer);
+ if (status != 0) {
+ fprintf(stderr, "I_NetlogonControl failed: Status = %d 0x%x %s\n",
+ status, status,
+ libnetapi_get_error_string(ctx, status));
+ goto done;
+ }
+
+ print_netlogon_info_result(query_level, buffer);
+
+ break;
+ case OPT_SC_CHANGE_PWD:
+ query_level = 1;
+ status = I_NetLogonControl2(opt_server,
+ NETLOGON_CONTROL_CHANGE_PASSWORD,
+ query_level,
+ (uint8_t *)opt_domain,
+ &buffer);
+ if (status != 0) {
+ fprintf(stderr, "I_NetlogonControl failed: Status = %d 0x%x %s\n",
+ status, status,
+ libnetapi_get_error_string(ctx, status));
+ goto done;
+ }
+
+ print_netlogon_info_result(query_level, buffer);
+
+ break;
+ case OPT_DSREGDNS:
+ query_level = 1;
+ status = I_NetLogonControl2(opt_server,
+ NETLOGON_CONTROL_FORCE_DNS_REG,
+ query_level,
+ NULL,
+ &buffer);
+ if (status != 0) {
+ fprintf(stderr, "I_NetlogonControl failed: Status = %d 0x%x %s\n",
+ status, status,
+ libnetapi_get_error_string(ctx, status));
+ goto done;
+ }
+
+ print_netlogon_info_result(query_level, buffer);
+
+ break;
+ case OPT_DSGETDC:
+ if (opt_pdc)
+ flags |= DS_PDC_REQUIRED;
+ if (opt_ds)
+ flags |= DS_DIRECTORY_SERVICE_REQUIRED;
+ if (opt_dsp)
+ flags |= DS_DIRECTORY_SERVICE_PREFERRED;
+ if (opt_kdc)
+ flags |= DS_KDC_REQUIRED;
+ if (opt_timeserv)
+ flags |= DS_TIMESERV_REQUIRED;
+ if (opt_gtimeserv)
+ flags |= DS_GOOD_TIMESERV_PREFERRED;
+ if (opt_ws)
+ flags |= DS_WEB_SERVICE_REQUIRED;
+ if (opt_netbios)
+ flags |= DS_IS_FLAT_NAME;
+ if (opt_dns)
+ flags |= DS_IS_DNS_NAME;
+ if (opt_ip)
+ flags |= DS_IP_REQUIRED;
+ if (opt_force)
+ flags |= DS_FORCE_REDISCOVERY;
+ if (opt_writable)
+ flags |= DS_WRITABLE_REQUIRED;
+ if (opt_avoidself)
+ flags |= DS_AVOID_SELF;
+ if (opt_ldaponly)
+ flags |= DS_ONLY_LDAP_NEEDED;
+ if (opt_backg)
+ flags |= DS_BACKGROUND_ONLY;
+ if (opt_ds_6)
+ flags |= DS_DIRECTORY_SERVICE_6_REQUIRED;
+ if (opt_try_next_closest_site)
+ flags |= DS_TRY_NEXTCLOSEST_SITE;
+ if (opt_ret_dns)
+ flags |= DS_RETURN_DNS_NAME;
+ if (opt_ret_netbios)
+ flags |= DS_RETURN_FLAT_NAME;
+
+ status = DsGetDcName(opt_server,
+ opt_domain,
+ NULL, /* domain_guid */
+ opt_site,
+ flags,
+ &dc_info);
+ if (status != 0) {
+ fprintf(stderr, "DsGetDcName failed: Status = %d 0x%x %s\n",
+ status, status,
+ libnetapi_get_error_string(ctx, status));
+ goto done;
+ }
+
+ print_dc_info(dc_info);
+
+ break;
+ default:
+ continue;
+ }
+ }
+
+ printf("The command completed successfully\n");
+ status = 0;
+
+ done:
+
+ printf("\n");
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/server/remote_tod.c b/source3/lib/netapi/examples/server/remote_tod.c
new file mode 100644
index 0000000..7636f6a
--- /dev/null
+++ b/source3/lib/netapi/examples/server/remote_tod.c
@@ -0,0 +1,83 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetRemoteTOD query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ struct TIME_OF_DAY_INFO *tod = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("tod", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+
+ /* NetRemoteTOD */
+
+ status = NetRemoteTOD(hostname,
+ (uint8_t **)&tod);
+ if (status != 0) {
+ printf("NetRemoteTOD failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ } else {
+ printf("%d-%d-%d %d:%d:%d\n",
+ tod->tod_day, tod->tod_month, tod->tod_year,
+ tod->tod_hours, tod->tod_mins, tod->tod_secs);
+ NetApiBufferFree(tod);
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/server/server_getinfo.c b/source3/lib/netapi/examples/server/server_getinfo.c
new file mode 100644
index 0000000..7836faa
--- /dev/null
+++ b/source3/lib/netapi/examples/server/server_getinfo.c
@@ -0,0 +1,136 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetServerGetInfo query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 100;
+
+ struct SERVER_INFO_100 *i100;
+ struct SERVER_INFO_101 *i101;
+ struct SERVER_INFO_102 *i102;
+ struct SERVER_INFO_1005 *i1005;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("server_getinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetServerGetInfo */
+
+ status = NetServerGetInfo(hostname,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("NetServerGetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ switch (level) {
+ case 100:
+ i100 = (struct SERVER_INFO_100 *)buffer;
+ printf("platform id: %d\n", i100->sv100_platform_id);
+ printf("name: %s\n", i100->sv100_name);
+ break;
+ case 101:
+ i101 = (struct SERVER_INFO_101 *)buffer;
+ printf("platform id: %d\n", i101->sv101_platform_id);
+ printf("name: %s\n", i101->sv101_name);
+ printf("version major: %d\n", i101->sv101_version_major);
+ printf("version minor: %d\n", i101->sv101_version_minor);
+ printf("type: 0x%08x\n", i101->sv101_type);
+ printf("comment: %s\n", i101->sv101_comment);
+ break;
+ case 102:
+ i102 = (struct SERVER_INFO_102 *)buffer;
+ printf("platform id: %d\n", i102->sv102_platform_id);
+ printf("name: %s\n", i102->sv102_name);
+ printf("version major: %d\n", i102->sv102_version_major);
+ printf("version minor: %d\n", i102->sv102_version_minor);
+ printf("type: 0x%08x\n", i102->sv102_type);
+ printf("comment: %s\n", i102->sv102_comment);
+ printf("users: %d\n", i102->sv102_users);
+ printf("disc: %d\n", i102->sv102_disc);
+ printf("hidden: %d\n", i102->sv102_hidden);
+ printf("announce: %d\n", i102->sv102_announce);
+ printf("anndelta: %d\n", i102->sv102_anndelta);
+ printf("licenses: %d\n", i102->sv102_licenses);
+ printf("userpath: %s\n", i102->sv102_userpath);
+ break;
+ case 402:
+ break;
+ case 403:
+ break;
+ case 502:
+ break;
+ case 503:
+ break;
+ case 1005:
+ i1005 = (struct SERVER_INFO_1005 *)buffer;
+ printf("comment: %s\n", i1005->sv1005_comment);
+ break;
+ default:
+ break;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/share/share_add.c b/source3/lib/netapi/examples/share/share_add.c
new file mode 100644
index 0000000..760381a
--- /dev/null
+++ b/source3/lib/netapi/examples/share/share_add.c
@@ -0,0 +1,105 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShareAdd query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *sharename = NULL;
+ const char *path = NULL;
+ uint32_t parm_err = 0;
+
+ struct SHARE_INFO_2 i2;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("share_add", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname sharename path");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ sharename = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ path = poptGetArg(pc);
+
+ /* NetShareAdd */
+
+ i2.shi2_netname = sharename;
+ i2.shi2_type = 0;
+ i2.shi2_remark = "Test share created via NetApi";
+ i2.shi2_permissions = 0;
+ i2.shi2_max_uses = (uint32_t)-1;
+ i2.shi2_current_uses = 0;
+ i2.shi2_path = path;
+ i2.shi2_passwd = NULL;
+
+ status = NetShareAdd(hostname,
+ 2,
+ (uint8_t *)&i2,
+ &parm_err);
+ if (status != 0) {
+ printf("NetShareAdd failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/share/share_del.c b/source3/lib/netapi/examples/share/share_del.c
new file mode 100644
index 0000000..20e3ce5
--- /dev/null
+++ b/source3/lib/netapi/examples/share/share_del.c
@@ -0,0 +1,85 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShareDel query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *sharename = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("share_del", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname sharename");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ sharename = poptGetArg(pc);
+
+ /* NetShareDel */
+
+ status = NetShareDel(hostname,
+ sharename,
+ 0);
+ if (status != 0) {
+ printf("NetShareDel failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/share/share_enum.c b/source3/lib/netapi/examples/share/share_enum.c
new file mode 100644
index 0000000..b1f4043
--- /dev/null
+++ b/source3/lib/netapi/examples/share/share_enum.c
@@ -0,0 +1,142 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShareEnum query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int i;
+
+ struct SHARE_INFO_0 *i0 = NULL;
+ struct SHARE_INFO_1 *i1 = NULL;
+ struct SHARE_INFO_2 *i2 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("share_enum", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetShareEnum */
+
+ do {
+ status = NetShareEnum(hostname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ printf("total entries: %d\n", total_entries);
+ switch (level) {
+ case 0:
+ i0 = (struct SHARE_INFO_0 *)buffer;
+ break;
+ case 1:
+ i1 = (struct SHARE_INFO_1 *)buffer;
+ break;
+ case 2:
+ i2 = (struct SHARE_INFO_2 *)buffer;
+ break;
+ default:
+ break;
+ }
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ printf("#%d netname: %s\n", i, i0->shi0_netname);
+ i0++;
+ break;
+ case 1:
+ printf("#%d netname: %s\n", i, i1->shi1_netname);
+ printf("#%d type: %d\n", i, i1->shi1_type);
+ printf("#%d remark: %s\n", i, i1->shi1_remark);
+ i1++;
+ break;
+ case 2:
+ printf("#%d netname: %s\n", i, i2->shi2_netname);
+ printf("#%d type: %d\n", i, i2->shi2_type);
+ printf("#%d remark: %s\n", i, i2->shi2_remark);
+ printf("#%d permissions: %d\n", i, i2->shi2_permissions);
+ printf("#%d max users: %d\n", i, i2->shi2_max_uses);
+ printf("#%d current users: %d\n", i, i2->shi2_current_uses);
+ printf("#%d path: %s\n", i, i2->shi2_path);
+ printf("#%d password: %s\n", i, i2->shi2_passwd);
+ i2++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetShareEnum failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/share/share_getinfo.c b/source3/lib/netapi/examples/share/share_getinfo.c
new file mode 100644
index 0000000..479da5c
--- /dev/null
+++ b/source3/lib/netapi/examples/share/share_getinfo.c
@@ -0,0 +1,152 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShareGetInfo query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *sharename = NULL;
+ uint32_t level = 2;
+ uint8_t *buffer = NULL;
+
+ struct SHARE_INFO_0 *i0 = NULL;
+ struct SHARE_INFO_1 *i1 = NULL;
+ struct SHARE_INFO_2 *i2 = NULL;
+ struct SHARE_INFO_501 *i501 = NULL;
+ struct SHARE_INFO_1005 *i1005 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("share_getinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname sharename level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ sharename = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetShareGetInfo */
+
+ status = NetShareGetInfo(hostname,
+ sharename,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("NetShareGetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ switch (level) {
+ case 0:
+ i0 = (struct SHARE_INFO_0 *)buffer;
+ break;
+ case 1:
+ i1 = (struct SHARE_INFO_1 *)buffer;
+ break;
+ case 2:
+ i2 = (struct SHARE_INFO_2 *)buffer;
+ break;
+ case 501:
+ i501 = (struct SHARE_INFO_501 *)buffer;
+ break;
+ case 1005:
+ i1005 = (struct SHARE_INFO_1005 *)buffer;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (level) {
+ case 0:
+ printf("netname: %s\n", i0->shi0_netname);
+ break;
+ case 1:
+ printf("netname: %s\n", i1->shi1_netname);
+ printf("type: %d\n", i1->shi1_type);
+ printf("remark: %s\n", i1->shi1_remark);
+ break;
+ case 2:
+ printf("netname: %s\n", i2->shi2_netname);
+ printf("type: %d\n", i2->shi2_type);
+ printf("remark: %s\n", i2->shi2_remark);
+ printf("permissions: %d\n", i2->shi2_permissions);
+ printf("max users: %d\n", i2->shi2_max_uses);
+ printf("current users: %d\n", i2->shi2_current_uses);
+ printf("path: %s\n", i2->shi2_path);
+ printf("password: %s\n", i2->shi2_passwd);
+ break;
+ case 501:
+ printf("netname: %s\n", i501->shi501_netname);
+ printf("type: %d\n", i501->shi501_type);
+ printf("remark: %s\n", i501->shi501_remark);
+ printf("flags: %d\n", i501->shi501_flags);
+ break;
+ case 1005:
+ printf("flags: %d\n", i1005->shi1005_flags);
+ break;
+ default:
+ break;
+ }
+ NetApiBufferFree(buffer);
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/share/share_setinfo.c b/source3/lib/netapi/examples/share/share_setinfo.c
new file mode 100644
index 0000000..f4748f4
--- /dev/null
+++ b/source3/lib/netapi/examples/share/share_setinfo.c
@@ -0,0 +1,105 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShareSetInfo query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *sharename = NULL;
+ const char *comment = "NetApi generated Share comment";
+ uint32_t level = 1004;
+ uint8_t *buffer = NULL;
+ uint32_t parm_err = 0;
+
+ struct SHARE_INFO_1004 i1004;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("share_setinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname sharename comment");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ sharename = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ comment = poptGetArg(pc);
+ }
+
+ /* NetShareSetInfo */
+ switch (level) {
+ case 1004:
+ i1004.shi1004_remark = comment;
+ buffer = (uint8_t *)&i1004;
+ break;
+ default:
+ break;
+ }
+
+ status = NetShareSetInfo(hostname,
+ sharename,
+ level,
+ buffer,
+ &parm_err);
+ if (status != 0) {
+ printf("NetShareSetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/shutdown/shutdown_abort.c b/source3/lib/netapi/examples/shutdown/shutdown_abort.c
new file mode 100644
index 0000000..8f24a7a
--- /dev/null
+++ b/source3/lib/netapi/examples/shutdown/shutdown_abort.c
@@ -0,0 +1,76 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShutdownAbort query
+ * Copyright (C) Guenther Deschner 2009
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("shutdown_abort", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ /* NetShutdownAbort */
+
+ status = NetShutdownAbort(hostname);
+ if (status != 0) {
+ printf("NetShutdownAbort failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/shutdown/shutdown_init.c b/source3/lib/netapi/examples/shutdown/shutdown_init.c
new file mode 100644
index 0000000..73d23bb
--- /dev/null
+++ b/source3/lib/netapi/examples/shutdown/shutdown_init.c
@@ -0,0 +1,94 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShutdownInit query
+ * Copyright (C) Guenther Deschner 2009
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *message = NULL;
+ uint32_t timeout = 30;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("shutdown_init", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname message timeout");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ message = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ timeout = atoi(poptGetArg(pc));
+
+ /* NetShutdownInit */
+
+ status = NetShutdownInit(hostname,
+ message,
+ timeout,
+ 1, /* close apps */
+ 1); /* reboot */
+ if (status != 0) {
+ printf("NetShutdownInit failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/user/user_add.c b/source3/lib/netapi/examples/user/user_add.c
new file mode 100644
index 0000000..5452f77
--- /dev/null
+++ b/source3/lib/netapi/examples/user/user_add.c
@@ -0,0 +1,103 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserAdd query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+ const char *password = NULL;
+ struct USER_INFO_1 info1;
+ uint32_t parm_error = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_add", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username password");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ password = poptGetArg(pc);
+
+ /* NetUserAdd */
+
+ info1.usri1_name = username;
+ info1.usri1_password = password;
+ info1.usri1_password_age = 0;
+ info1.usri1_priv = 0;
+ info1.usri1_home_dir = NULL;
+ info1.usri1_comment = "User created using Samba NetApi Example code";
+ info1.usri1_flags = 0;
+ info1.usri1_script_path = NULL;
+
+ status = NetUserAdd(hostname,
+ 1,
+ (uint8_t *)&info1,
+ &parm_error);
+ if (status != 0) {
+ printf("NetUserAdd failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/user/user_chgpwd.c b/source3/lib/netapi/examples/user/user_chgpwd.c
new file mode 100644
index 0000000..8b37ec2
--- /dev/null
+++ b/source3/lib/netapi/examples/user/user_chgpwd.c
@@ -0,0 +1,99 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserChangePassword query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+ const char *old_password = NULL;
+ const char *new_password = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_chgpwd", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username old_password new_password");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ old_password = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ new_password = poptGetArg(pc);
+
+ /* NetUserChangePassword */
+
+ status = NetUserChangePassword(hostname,
+ username,
+ old_password,
+ new_password);
+ if (status != 0) {
+ printf("NetUserChangePassword failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/user/user_del.c b/source3/lib/netapi/examples/user/user_del.c
new file mode 100644
index 0000000..9cf28a9
--- /dev/null
+++ b/source3/lib/netapi/examples/user/user_del.c
@@ -0,0 +1,82 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserDel query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_del", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ /* NetUserDel */
+
+ status = NetUserDel(hostname, username);
+ if (status != 0) {
+ printf("NetUserDel failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/user/user_dispinfo.c b/source3/lib/netapi/examples/user/user_dispinfo.c
new file mode 100644
index 0000000..23024fe
--- /dev/null
+++ b/source3/lib/netapi/examples/user/user_dispinfo.c
@@ -0,0 +1,100 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetQueryDisplayInformation query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ void *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t idx = 0;
+ int i;
+
+ struct NET_DISPLAY_USER *user;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_dispinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ /* NetQueryDisplayInformation */
+
+ do {
+ status = NetQueryDisplayInformation(hostname,
+ 1,
+ idx,
+ 1000,
+ (uint32_t)-1,
+ &entries_read,
+ &buffer);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ user = (struct NET_DISPLAY_USER *)buffer;
+ for (i=0; i<entries_read; i++) {
+ printf("user %d: %s\n", i + idx,
+ user->usri1_name);
+ user++;
+ }
+ NetApiBufferFree(buffer);
+ }
+ idx += entries_read;
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetQueryDisplayInformation failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/user/user_enum.c b/source3/lib/netapi/examples/user/user_enum.c
new file mode 100644
index 0000000..cf77bf2
--- /dev/null
+++ b/source3/lib/netapi/examples/user/user_enum.c
@@ -0,0 +1,157 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserEnum query
+ * Copyright (C) Guenther Deschner 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ char *sid_str = NULL;
+ int i;
+
+ struct USER_INFO_0 *info0 = NULL;
+ struct USER_INFO_10 *info10 = NULL;
+ struct USER_INFO_20 *info20 = NULL;
+ struct USER_INFO_23 *info23 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_enum", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetUserEnum */
+
+ do {
+ status = NetUserEnum(hostname,
+ level,
+ FILTER_NORMAL_ACCOUNT,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+
+ switch (level) {
+ case 0:
+ info0 = (struct USER_INFO_0 *)buffer;
+ break;
+ case 10:
+ info10 = (struct USER_INFO_10 *)buffer;
+ break;
+ case 20:
+ info20 = (struct USER_INFO_20 *)buffer;
+ break;
+ case 23:
+ info23 = (struct USER_INFO_23 *)buffer;
+ break;
+ default:
+ break;
+ }
+
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ printf("#%d user: %s\n", i, info0->usri0_name);
+ info0++;
+ break;
+ case 10:
+ printf("#%d user: %s\n", i, info10->usri10_name);
+ printf("#%d comment: %s\n", i, info10->usri10_comment);
+ printf("#%d usr_comment: %s\n", i, info10->usri10_usr_comment);
+ printf("#%d full_name: %s\n", i, info10->usri10_full_name);
+ info10++;
+ break;
+ case 20:
+ printf("#%d user: %s\n", i, info20->usri20_name);
+ printf("#%d comment: %s\n", i, info20->usri20_comment);
+ printf("#%d flags: 0x%08x\n", i, info20->usri20_flags);
+ printf("#%d rid: %d\n", i, info20->usri20_user_id);
+ info20++;
+ break;
+ case 23:
+ printf("#%d user: %s\n", i, info23->usri23_name);
+ printf("#%d comment: %s\n", i, info23->usri23_comment);
+ printf("#%d flags: 0x%08x\n", i, info23->usri23_flags);
+ if (ConvertSidToStringSid(info23->usri23_user_sid,
+ &sid_str)) {
+ printf("#%d sid: %s\n", i, sid_str);
+ free(sid_str);
+ }
+ info23++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetUserEnum failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/user/user_getgroups.c b/source3/lib/netapi/examples/user/user_getgroups.c
new file mode 100644
index 0000000..939415e
--- /dev/null
+++ b/source3/lib/netapi/examples/user/user_getgroups.c
@@ -0,0 +1,133 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserGetGroups query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ int i;
+
+ struct GROUP_USERS_INFO_0 *info0 = NULL;
+ struct GROUP_USERS_INFO_1 *info1 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_getgroups", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetUserGetGroups */
+
+ do {
+ status = NetUserGetGroups(hostname,
+ username,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+
+ switch (level) {
+ case 0:
+ info0 = (struct GROUP_USERS_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct GROUP_USERS_INFO_1 *)buffer;
+ break;
+ default:
+ break;
+ }
+
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ printf("#%d group: %s\n", i, info0->grui0_name);
+ info0++;
+ break;
+ case 1:
+ printf("#%d group: %s\n", i, info1->grui1_name);
+ printf("#%d attributes: %d\n", i, info1->grui1_attributes);
+ info1++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetUserGetGroups failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/user/user_getinfo.c b/source3/lib/netapi/examples/user/user_getinfo.c
new file mode 100644
index 0000000..9e95260
--- /dev/null
+++ b/source3/lib/netapi/examples/user/user_getinfo.c
@@ -0,0 +1,293 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserGetInfo query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 0;
+ char *sid_str = NULL;
+ int i;
+
+ struct USER_INFO_0 *u0;
+ struct USER_INFO_1 *u1;
+ struct USER_INFO_2 *u2;
+ struct USER_INFO_3 *u3;
+ struct USER_INFO_4 *u4;
+ struct USER_INFO_10 *u10;
+ struct USER_INFO_11 *u11;
+ struct USER_INFO_20 *u20;
+ struct USER_INFO_23 *u23;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_getinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetUserGetInfo */
+
+ status = NetUserGetInfo(hostname,
+ username,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("NetUserGetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ switch (level) {
+ case 0:
+ u0 = (struct USER_INFO_0 *)buffer;
+ printf("name: %s\n", u0->usri0_name);
+ break;
+ case 1:
+ u1 = (struct USER_INFO_1 *)buffer;
+ printf("name: %s\n", u1->usri1_name);
+ printf("password: %s\n", u1->usri1_password);
+ printf("password_age: %d\n", u1->usri1_password_age);
+ printf("priv: %d\n", u1->usri1_priv);
+ printf("homedir: %s\n", u1->usri1_home_dir);
+ printf("comment: %s\n", u1->usri1_comment);
+ printf("flags: 0x%08x\n", u1->usri1_flags);
+ printf("script: %s\n", u1->usri1_script_path);
+ break;
+ case 2:
+ u2 = (struct USER_INFO_2 *)buffer;
+ printf("name: %s\n", u2->usri2_name);
+ printf("password: %s\n", u2->usri2_password);
+ printf("password_age: %d\n", u2->usri2_password_age);
+ printf("priv: %d\n", u2->usri2_priv);
+ printf("homedir: %s\n", u2->usri2_home_dir);
+ printf("comment: %s\n", u2->usri2_comment);
+ printf("flags: 0x%08x\n", u2->usri2_flags);
+ printf("script: %s\n", u2->usri2_script_path);
+ printf("auth flags: 0x%08x\n", u2->usri2_auth_flags);
+ printf("full name: %s\n", u2->usri2_full_name);
+ printf("user comment: %s\n", u2->usri2_usr_comment);
+ printf("user parameters: %s\n", u2->usri2_parms);
+ printf("workstations: %s\n", u2->usri2_workstations);
+ printf("last logon (seconds since jan. 1, 1970 GMT): %d\n",
+ u2->usri2_last_logon);
+ printf("last logoff (seconds since jan. 1, 1970 GMT): %d\n",
+ u2->usri2_last_logoff);
+ printf("account expires (seconds since jan. 1, 1970 GMT): %d\n",
+ u2->usri2_acct_expires);
+ printf("max storage: %d\n", u2->usri2_max_storage);
+ printf("units per week: %d\n", u2->usri2_units_per_week);
+ printf("logon hours:");
+ for (i=0; i<21; i++) {
+ printf(" %x", (uint8_t)u2->usri2_logon_hours[i]);
+ }
+ printf("\n");
+ printf("bad password count: %d\n", u2->usri2_bad_pw_count);
+ printf("logon count: %d\n", u2->usri2_num_logons);
+ printf("logon server: %s\n", u2->usri2_logon_server);
+ printf("country code: %d\n", u2->usri2_country_code);
+ printf("code page: %d\n", u2->usri2_code_page);
+ break;
+ case 3:
+ u3 = (struct USER_INFO_3 *)buffer;
+ printf("name: %s\n", u3->usri3_name);
+ printf("password_age: %d\n", u3->usri3_password_age);
+ printf("priv: %d\n", u3->usri3_priv);
+ printf("homedir: %s\n", u3->usri3_home_dir);
+ printf("comment: %s\n", u3->usri3_comment);
+ printf("flags: 0x%08x\n", u3->usri3_flags);
+ printf("script: %s\n", u3->usri3_script_path);
+ printf("auth flags: 0x%08x\n", u3->usri3_auth_flags);
+ printf("full name: %s\n", u3->usri3_full_name);
+ printf("user comment: %s\n", u3->usri3_usr_comment);
+ printf("user parameters: %s\n", u3->usri3_parms);
+ printf("workstations: %s\n", u3->usri3_workstations);
+ printf("last logon (seconds since jan. 1, 1970 GMT): %d\n",
+ u3->usri3_last_logon);
+ printf("last logoff (seconds since jan. 1, 1970 GMT): %d\n",
+ u3->usri3_last_logoff);
+ printf("account expires (seconds since jan. 1, 1970 GMT): %d\n",
+ u3->usri3_acct_expires);
+ printf("max storage: %d\n", u3->usri3_max_storage);
+ printf("units per week: %d\n", u3->usri3_units_per_week);
+ printf("logon hours:");
+ for (i=0; i<21; i++) {
+ printf(" %x", (uint8_t)u3->usri3_logon_hours[i]);
+ }
+ printf("\n");
+ printf("bad password count: %d\n", u3->usri3_bad_pw_count);
+ printf("logon count: %d\n", u3->usri3_num_logons);
+ printf("logon server: %s\n", u3->usri3_logon_server);
+ printf("country code: %d\n", u3->usri3_country_code);
+ printf("code page: %d\n", u3->usri3_code_page);
+ printf("user id: %d\n", u3->usri3_user_id);
+ printf("primary group id: %d\n", u3->usri3_primary_group_id);
+ printf("profile: %s\n", u3->usri3_profile);
+ printf("home dir drive: %s\n", u3->usri3_home_dir_drive);
+ printf("password expired: %d\n", u3->usri3_password_expired);
+ break;
+ case 4:
+ u4 = (struct USER_INFO_4 *)buffer;
+ printf("name: %s\n", u4->usri4_name);
+ printf("password: %s\n", u4->usri4_password);
+ printf("password_age: %d\n", u4->usri4_password_age);
+ printf("priv: %d\n", u4->usri4_priv);
+ printf("homedir: %s\n", u4->usri4_home_dir);
+ printf("comment: %s\n", u4->usri4_comment);
+ printf("flags: 0x%08x\n", u4->usri4_flags);
+ printf("script: %s\n", u4->usri4_script_path);
+ printf("auth flags: 0x%08x\n", u4->usri4_auth_flags);
+ printf("full name: %s\n", u4->usri4_full_name);
+ printf("user comment: %s\n", u4->usri4_usr_comment);
+ printf("user parameters: %s\n", u4->usri4_parms);
+ printf("workstations: %s\n", u4->usri4_workstations);
+ printf("last logon (seconds since jan. 1, 1970 GMT): %d\n",
+ u4->usri4_last_logon);
+ printf("last logoff (seconds since jan. 1, 1970 GMT): %d\n",
+ u4->usri4_last_logoff);
+ printf("account expires (seconds since jan. 1, 1970 GMT): %d\n",
+ u4->usri4_acct_expires);
+ printf("max storage: %d\n", u4->usri4_max_storage);
+ printf("units per week: %d\n", u4->usri4_units_per_week);
+ printf("logon hours:");
+ for (i=0; i<21; i++) {
+ printf(" %x", (uint8_t)u4->usri4_logon_hours[i]);
+ }
+ printf("\n");
+ printf("bad password count: %d\n", u4->usri4_bad_pw_count);
+ printf("logon count: %d\n", u4->usri4_num_logons);
+ printf("logon server: %s\n", u4->usri4_logon_server);
+ printf("country code: %d\n", u4->usri4_country_code);
+ printf("code page: %d\n", u4->usri4_code_page);
+ if (ConvertSidToStringSid(u4->usri4_user_sid,
+ &sid_str)) {
+ printf("user_sid: %s\n", sid_str);
+ free(sid_str);
+ }
+ printf("primary group id: %d\n", u4->usri4_primary_group_id);
+ printf("profile: %s\n", u4->usri4_profile);
+ printf("home dir drive: %s\n", u4->usri4_home_dir_drive);
+ printf("password expired: %d\n", u4->usri4_password_expired);
+ break;
+ case 10:
+ u10 = (struct USER_INFO_10 *)buffer;
+ printf("name: %s\n", u10->usri10_name);
+ printf("comment: %s\n", u10->usri10_comment);
+ printf("usr_comment: %s\n", u10->usri10_usr_comment);
+ printf("full_name: %s\n", u10->usri10_full_name);
+ break;
+ case 11:
+ u11 = (struct USER_INFO_11 *)buffer;
+ printf("name: %s\n", u11->usri11_name);
+ printf("comment: %s\n", u11->usri11_comment);
+ printf("user comment: %s\n", u11->usri11_usr_comment);
+ printf("full name: %s\n", u11->usri11_full_name);
+ printf("priv: %d\n", u11->usri11_priv);
+ printf("auth flags: 0x%08x\n", u11->usri11_auth_flags);
+ printf("password_age: %d\n", u11->usri11_password_age);
+ printf("homedir: %s\n", u11->usri11_home_dir);
+ printf("user parameters: %s\n", u11->usri11_parms);
+ printf("last logon (seconds since jan. 1, 1970 GMT): %d\n",
+ u11->usri11_last_logon);
+ printf("last logoff (seconds since jan. 1, 1970 GMT): %d\n",
+ u11->usri11_last_logoff);
+ printf("bad password count: %d\n", u11->usri11_bad_pw_count);
+ printf("logon count: %d\n", u11->usri11_num_logons);
+ printf("logon server: %s\n", u11->usri11_logon_server);
+ printf("country code: %d\n", u11->usri11_country_code);
+ printf("workstations: %s\n", u11->usri11_workstations);
+ printf("max storage: %d\n", u11->usri11_max_storage);
+ printf("units per week: %d\n", u11->usri11_units_per_week);
+ printf("logon hours:");
+ for (i=0; i<21; i++) {
+ printf(" %x", (uint8_t)u11->usri11_logon_hours[i]);
+ }
+ printf("\n");
+ printf("code page: %d\n", u11->usri11_code_page);
+ break;
+ case 20:
+ u20 = (struct USER_INFO_20 *)buffer;
+ printf("name: %s\n", u20->usri20_name);
+ printf("comment: %s\n", u20->usri20_comment);
+ printf("flags: 0x%08x\n", u20->usri20_flags);
+ printf("rid: %d\n", u20->usri20_user_id);
+ break;
+ case 23:
+ u23 = (struct USER_INFO_23 *)buffer;
+ printf("name: %s\n", u23->usri23_name);
+ printf("comment: %s\n", u23->usri23_comment);
+ printf("flags: 0x%08x\n", u23->usri23_flags);
+ if (ConvertSidToStringSid(u23->usri23_user_sid,
+ &sid_str)) {
+ printf("user_sid: %s\n", sid_str);
+ free(sid_str);
+ }
+ break;
+ default:
+ break;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/user/user_getlocalgroups.c b/source3/lib/netapi/examples/user/user_getlocalgroups.c
new file mode 100644
index 0000000..133104d
--- /dev/null
+++ b/source3/lib/netapi/examples/user/user_getlocalgroups.c
@@ -0,0 +1,122 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserGetLocalGroups query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t flags = 0;
+ int i;
+
+ struct LOCALGROUP_USERS_INFO_0 *info0 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_getlocalgroups", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ /* NetUserGetLocalGroups */
+
+ do {
+ status = NetUserGetLocalGroups(hostname,
+ username,
+ level,
+ flags,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+
+ switch (level) {
+ case 0:
+ info0 = (struct LOCALGROUP_USERS_INFO_0 *)buffer;
+ break;
+ default:
+ break;
+ }
+
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ printf("#%d group: %s\n", i, info0->lgrui0_name);
+ info0++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetUserGetLocalGroups failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/user/user_modalsget.c b/source3/lib/netapi/examples/user/user_modalsget.c
new file mode 100644
index 0000000..4dcb41b
--- /dev/null
+++ b/source3/lib/netapi/examples/user/user_modalsget.c
@@ -0,0 +1,131 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserModalsGet query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 0;
+ char *sid_str = NULL;
+
+ struct USER_MODALS_INFO_0 *u0;
+ struct USER_MODALS_INFO_1 *u1;
+ struct USER_MODALS_INFO_2 *u2;
+ struct USER_MODALS_INFO_3 *u3;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_modalsget", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetUserModalsGet */
+
+ status = NetUserModalsGet(hostname,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("NetUserModalsGet failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ switch (level) {
+ case 0:
+ u0 = (struct USER_MODALS_INFO_0 *)buffer;
+ printf("min passwd len: %d character\n",
+ u0->usrmod0_min_passwd_len);
+ printf("max passwd age: %d (days)\n",
+ u0->usrmod0_max_passwd_age/86400);
+ printf("min passwd age: %d (days)\n",
+ u0->usrmod0_min_passwd_age/86400);
+ printf("force logoff: %d (seconds)\n",
+ u0->usrmod0_force_logoff);
+ printf("password history length: %d entries\n",
+ u0->usrmod0_password_hist_len);
+ break;
+ case 1:
+ u1 = (struct USER_MODALS_INFO_1 *)buffer;
+ printf("role: %d\n", u1->usrmod1_role);
+ printf("primary: %s\n", u1->usrmod1_primary);
+ break;
+ case 2:
+ u2 = (struct USER_MODALS_INFO_2 *)buffer;
+ printf("domain name: %s\n", u2->usrmod2_domain_name);
+ if (ConvertSidToStringSid(u2->usrmod2_domain_id,
+ &sid_str)) {
+ printf("domain sid: %s\n", sid_str);
+ free(sid_str);
+ }
+ break;
+ case 3:
+ u3 = (struct USER_MODALS_INFO_3 *)buffer;
+ printf("lockout duration: %d (seconds)\n",
+ u3->usrmod3_lockout_duration);
+ printf("lockout observation window: %d (seconds)\n",
+ u3->usrmod3_lockout_observation_window);
+ printf("lockout threshold: %d entries\n",
+ u3->usrmod3_lockout_threshold);
+ break;
+ default:
+ break;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/user/user_modalsset.c b/source3/lib/netapi/examples/user/user_modalsset.c
new file mode 100644
index 0000000..a5cdc44
--- /dev/null
+++ b/source3/lib/netapi/examples/user/user_modalsset.c
@@ -0,0 +1,132 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserModalsSet query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 0;
+ uint32_t parm_err = 0;
+
+ struct USER_MODALS_INFO_0 u0;
+ struct USER_MODALS_INFO_1001 u1001;
+ struct USER_MODALS_INFO_1002 u1002;
+ struct USER_MODALS_INFO_1003 u1003;
+ struct USER_MODALS_INFO_1004 u1004;
+ struct USER_MODALS_INFO_1005 u1005;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_modalsset", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname level value");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ switch (level) {
+ case 0:
+ u0.usrmod0_min_passwd_len = 0;
+ u0.usrmod0_max_passwd_age = (86400 * 30); /* once a month */
+ u0.usrmod0_min_passwd_age = 0;
+ u0.usrmod0_force_logoff = TIMEQ_FOREVER;
+ u0.usrmod0_password_hist_len = 0;
+ buffer = (uint8_t *)&u0;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ break;
+ case 1001:
+ u1001.usrmod1001_min_passwd_len = 0;
+ buffer = (uint8_t *)&u1001;
+ break;
+ case 1002:
+ u1002.usrmod1002_max_passwd_age = 0;
+ buffer = (uint8_t *)&u1002;
+ break;
+ case 1003:
+ u1003.usrmod1003_min_passwd_age = (86400 * 30); /* once a month */
+ buffer = (uint8_t *)&u1003;
+ break;
+ case 1004:
+ u1004.usrmod1004_force_logoff = TIMEQ_FOREVER;
+ buffer = (uint8_t *)&u1004;
+ break;
+ case 1005:
+ u1005.usrmod1005_password_hist_len = 0;
+ buffer = (uint8_t *)&u1005;
+ break;
+ case 1006:
+ case 1007:
+ default:
+ break;
+ }
+
+ /* NetUserModalsSet */
+
+ status = NetUserModalsSet(hostname,
+ level,
+ buffer,
+ &parm_err);
+ if (status != 0) {
+ printf("NetUserModalsSet failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/user/user_setgroups.c b/source3/lib/netapi/examples/user/user_setgroups.c
new file mode 100644
index 0000000..de3ff22
--- /dev/null
+++ b/source3/lib/netapi/examples/user/user_setgroups.c
@@ -0,0 +1,144 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserSetGroups query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t num_entries = 0;
+ const char **names = NULL;
+ int i = 0;
+ size_t buf_size = 0;
+
+ struct GROUP_USERS_INFO_0 *g0 = NULL;
+ struct GROUP_USERS_INFO_1 *g1 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_setgroups", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username group1 group2 ...");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+
+ names = poptGetArgs(pc);
+ for (i=0; names[i] != NULL; i++) {
+ num_entries++;
+ }
+
+ switch (level) {
+ case 0:
+ buf_size = sizeof(struct GROUP_USERS_INFO_0) * num_entries;
+
+ status = NetApiBufferAllocate(buf_size, (void **)&g0);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<num_entries; i++) {
+ g0[i].grui0_name = names[i];
+ }
+
+ buffer = (uint8_t *)g0;
+ break;
+ case 1:
+ buf_size = sizeof(struct GROUP_USERS_INFO_1) * num_entries;
+
+ status = NetApiBufferAllocate(buf_size, (void **)&g1);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<num_entries; i++) {
+ g1[i].grui1_name = names[i];
+ g1[i].grui1_attributes = 0; /* ? */
+ }
+
+ buffer = (uint8_t *)g1;
+ break;
+ default:
+ break;
+ }
+
+ /* NetUserSetGroups */
+
+ status = NetUserSetGroups(hostname,
+ username,
+ level,
+ buffer,
+ num_entries);
+ if (status != 0) {
+ printf("NetUserSetGroups failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ NetApiBufferFree(buffer);
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/user/user_setinfo.c b/source3/lib/netapi/examples/user/user_setinfo.c
new file mode 100644
index 0000000..56c9822
--- /dev/null
+++ b/source3/lib/netapi/examples/user/user_setinfo.c
@@ -0,0 +1,200 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserSetInfo query
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+ uint32_t level = 0;
+ uint32_t parm_err = 0;
+ uint8_t *buffer = NULL;
+ const char *val = NULL;
+
+ struct USER_INFO_0 u0;
+ struct USER_INFO_1003 u1003;
+ struct USER_INFO_1005 u1005;
+ struct USER_INFO_1006 u1006;
+ struct USER_INFO_1007 u1007;
+ struct USER_INFO_1008 u1008;
+ struct USER_INFO_1009 u1009;
+ struct USER_INFO_1010 u1010;
+ struct USER_INFO_1011 u1011;
+ struct USER_INFO_1012 u1012;
+ struct USER_INFO_1014 u1014;
+ struct USER_INFO_1017 u1017;
+ struct USER_INFO_1024 u1024;
+ struct USER_INFO_1051 u1051;
+ struct USER_INFO_1052 u1052;
+ struct USER_INFO_1053 u1053;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_setinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ level = atoi(poptGetArg(pc));
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ val = poptGetArg(pc);
+
+ /* NetUserSetInfo */
+
+ switch (level) {
+ case 0:
+ u0.usri0_name = val;
+ buffer = (uint8_t *)&u0;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ break;
+ case 21:
+ break;
+ case 22:
+ break;
+ case 1003:
+ u1003.usri1003_password = val;
+ buffer = (uint8_t *)&u1003;
+ break;
+ case 1005:
+ u1005.usri1005_priv = atoi(val);
+ buffer = (uint8_t *)&u1005;
+ break;
+ case 1006:
+ u1006.usri1006_home_dir = val;
+ buffer = (uint8_t *)&u1006;
+ break;
+ case 1007:
+ u1007.usri1007_comment = val;
+ buffer = (uint8_t *)&u1007;
+ break;
+ case 1008:
+ u1008.usri1008_flags = atoi(val);
+ buffer = (uint8_t *)&u1008;
+ break;
+ case 1009:
+ u1009.usri1009_script_path = val;
+ buffer = (uint8_t *)&u1009;
+ break;
+ case 1010:
+ u1010.usri1010_auth_flags = atoi(val);
+ buffer = (uint8_t *)&u1010;
+ break;
+ case 1011:
+ u1011.usri1011_full_name = val;
+ buffer = (uint8_t *)&u1011;
+ break;
+ case 1012:
+ u1012.usri1012_usr_comment = val;
+ buffer = (uint8_t *)&u1012;
+ break;
+ case 1014:
+ u1014.usri1014_workstations = val;
+ buffer = (uint8_t *)&u1014;
+ break;
+ case 1017:
+ u1017.usri1017_acct_expires = atoi(val);
+ buffer = (uint8_t *)&u1017;
+ break;
+ case 1020:
+ break;
+ case 1024:
+ u1024.usri1024_country_code = atoi(val);
+ buffer = (uint8_t *)&u1024;
+ break;
+ case 1051:
+ u1051.usri1051_primary_group_id = atoi(val);
+ buffer = (uint8_t *)&u1051;
+ break;
+ case 1052:
+ u1052.usri1052_profile = val;
+ buffer = (uint8_t *)&u1052;
+ break;
+ case 1053:
+ u1053.usri1053_home_dir_drive = val;
+ buffer = (uint8_t *)&u1053;
+ break;
+ default:
+ break;
+ }
+
+ status = NetUserSetInfo(hostname,
+ username,
+ level,
+ buffer,
+ &parm_err);
+ if (status != 0) {
+ printf("NetUserSetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/wscript_build b/source3/lib/netapi/examples/wscript_build
new file mode 100644
index 0000000..1d56840
--- /dev/null
+++ b/source3/lib/netapi/examples/wscript_build
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+
+# The remaining task is to build the gtk example, but we first need to find the gtk libs
+# netdomjoin-gui/netdomjoin-gui.c
+
+names = [
+ ("getdc", "getdc"),
+ ("dsgetdc", "dsgetdc"),
+ ("join", "netdomjoin"),
+ ("join", "getjoinableous"),
+ ("join", "getjoininformation"),
+ ("join", "rename_machine"),
+ ("join", "provision_computer_account"),
+ ("join", "request_offline_domain_join"),
+ ("join", "djoin"),
+ ("user", "user_add"),
+ ("user", "user_del"),
+ ("user", "user_enum"),
+ ("user", "user_dispinfo"),
+ ("user", "user_chgpwd"),
+ ("user", "user_getinfo"),
+ ("user", "user_setinfo"),
+ ("user", "user_modalsget"),
+ ("user", "user_modalsset"),
+ ("user", "user_getgroups"),
+ ("user", "user_setgroups"),
+ ("user", "user_getlocalgroups"),
+ ("group", "group_add"),
+ ("group", "group_del"),
+ ("group", "group_enum"),
+ ("group", "group_setinfo"),
+ ("group", "group_getinfo"),
+ ("group", "group_adduser"),
+ ("group", "group_deluser"),
+ ("group", "group_getusers"),
+ ("group", "group_setusers"),
+ ("localgroup", "localgroup_add"),
+ ("localgroup", "localgroup_del"),
+ ("localgroup", "localgroup_getinfo"),
+ ("localgroup", "localgroup_setinfo"),
+ ("localgroup", "localgroup_enum"),
+ ("localgroup", "localgroup_addmembers"),
+ ("localgroup", "localgroup_delmembers"),
+ ("localgroup", "localgroup_setmembers"),
+ ("localgroup", "localgroup_getmembers"),
+ ("server", "remote_tod"),
+ ("server", "server_getinfo"),
+ ("share", "share_add"),
+ ("share", "share_del"),
+ ("share", "share_enum"),
+ ("share", "share_getinfo"),
+ ("share", "share_setinfo"),
+ ("file", "file_close"),
+ ("file", "file_getinfo"),
+ ("file", "file_enum"),
+ ("shutdown", "shutdown_init"),
+ ("shutdown", "shutdown_abort"),
+ ("netlogon", "netlogon_control"),
+ ("netlogon", "netlogon_control2"),
+ ("netlogon", "nltest")]
+
+
+bld.SAMBA_SUBSYSTEM('LIBNETAPI_EXAMPLES_COMMON',
+ source='common.c',
+ deps='netapi popt')
+
+for pattern in names:
+ (subdir, name) = pattern
+ bld.SAMBA_BINARY('%s/%s' % (subdir, name),
+ source='%s/%s.c' % (subdir, name),
+ deps='netapi popt LIBNETAPI_EXAMPLES_COMMON',
+ install=False)
diff --git a/source3/lib/netapi/file.c b/source3/lib/netapi/file.c
new file mode 100644
index 0000000..411747a
--- /dev/null
+++ b/source3/lib/netapi/file.c
@@ -0,0 +1,283 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi File Support
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+#include "../librpc/gen_ndr/ndr_srvsvc_c.h"
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetFileClose_r(struct libnetapi_ctx *ctx,
+ struct NetFileClose *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct dcerpc_binding_handle *b;
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_srvsvc,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_srvsvc_NetFileClose(b, talloc_tos(),
+ r->in.server_name,
+ r->in.fileid,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetFileClose_l(struct libnetapi_ctx *ctx,
+ struct NetFileClose *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetFileClose);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS map_srvsvc_FileInfo_to_FILE_INFO_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ union srvsvc_NetFileInfo *info,
+ uint8_t **buffer,
+ uint32_t *num_entries)
+{
+ struct FILE_INFO_2 i2;
+ struct FILE_INFO_3 i3;
+
+ switch (level) {
+ case 2:
+ i2.fi2_id = info->info2->fid;
+
+ ADD_TO_ARRAY(mem_ctx, struct FILE_INFO_2, i2,
+ (struct FILE_INFO_2 **)buffer,
+ num_entries);
+ break;
+ case 3:
+ i3.fi3_id = info->info3->fid;
+ i3.fi3_permissions = info->info3->permissions;
+ i3.fi3_num_locks = info->info3->num_locks;
+ i3.fi3_pathname = talloc_strdup(mem_ctx, info->info3->path);
+ i3.fi3_username = talloc_strdup(mem_ctx, info->info3->user);
+
+ NT_STATUS_HAVE_NO_MEMORY(i3.fi3_pathname);
+ NT_STATUS_HAVE_NO_MEMORY(i3.fi3_username);
+
+ ADD_TO_ARRAY(mem_ctx, struct FILE_INFO_3, i3,
+ (struct FILE_INFO_3 **)buffer,
+ num_entries);
+ break;
+ default:
+ return NT_STATUS_INVALID_INFO_CLASS;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetFileGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetFileGetInfo *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ union srvsvc_NetFileInfo info;
+ uint32_t num_entries = 0;
+ struct dcerpc_binding_handle *b;
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 2:
+ case 3:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_srvsvc,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_srvsvc_NetFileGetInfo(b, talloc_tos(),
+ r->in.server_name,
+ r->in.fileid,
+ r->in.level,
+ &info,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = map_srvsvc_FileInfo_to_FILE_INFO_buffer(ctx,
+ r->in.level,
+ &info,
+ r->out.buffer,
+ &num_entries);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetFileGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetFileGetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetFileGetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetFileEnum_r(struct libnetapi_ctx *ctx,
+ struct NetFileEnum *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct srvsvc_NetFileInfoCtr info_ctr;
+ struct srvsvc_NetFileCtr2 ctr2;
+ struct srvsvc_NetFileCtr3 ctr3;
+ uint32_t num_entries = 0;
+ uint32_t i;
+ struct dcerpc_binding_handle *b;
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 2:
+ case 3:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_srvsvc,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ ZERO_STRUCT(info_ctr);
+
+ info_ctr.level = r->in.level;
+ switch (r->in.level) {
+ case 2:
+ ZERO_STRUCT(ctr2);
+ info_ctr.ctr.ctr2 = &ctr2;
+ break;
+ case 3:
+ ZERO_STRUCT(ctr3);
+ info_ctr.ctr.ctr3 = &ctr3;
+ break;
+ }
+
+ status = dcerpc_srvsvc_NetFileEnum(b, talloc_tos(),
+ r->in.server_name,
+ r->in.base_path,
+ r->in.user_name,
+ &info_ctr,
+ r->in.prefmaxlen,
+ r->out.total_entries,
+ r->out.resume_handle,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!W_ERROR_IS_OK(werr) && !W_ERROR_EQUAL(werr, WERR_MORE_DATA)) {
+ goto done;
+ }
+
+ for (i=0; i < info_ctr.ctr.ctr2->count; i++) {
+ union srvsvc_NetFileInfo _i = {0};
+ switch (r->in.level) {
+ case 2:
+ _i.info2 = &info_ctr.ctr.ctr2->array[i];
+ break;
+ case 3:
+ _i.info3 = &info_ctr.ctr.ctr3->array[i];
+ break;
+ }
+
+ status = map_srvsvc_FileInfo_to_FILE_INFO_buffer(ctx,
+ r->in.level,
+ &_i,
+ r->out.buffer,
+ &num_entries);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ if (r->out.entries_read) {
+ *r->out.entries_read = num_entries;
+ }
+
+ if (r->out.total_entries) {
+ *r->out.total_entries = num_entries;
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetFileEnum_l(struct libnetapi_ctx *ctx,
+ struct NetFileEnum *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetFileEnum);
+}
diff --git a/source3/lib/netapi/getdc.c b/source3/lib/netapi/getdc.c
new file mode 100644
index 0000000..7e5fab3
--- /dev/null
+++ b/source3/lib/netapi/getdc.c
@@ -0,0 +1,212 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi GetDC Support
+ * Copyright (C) Guenther Deschner 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "../librpc/gen_ndr/ndr_netlogon_c.h"
+#include "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+#include "libsmb/dsgetdcname.h"
+
+/********************************************************************
+********************************************************************/
+
+WERROR NetGetDCName_l(struct libnetapi_ctx *ctx,
+ struct NetGetDCName *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGetDCName);
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR NetGetDCName_r(struct libnetapi_ctx *ctx,
+ struct NetGetDCName *r)
+{
+ NTSTATUS status;
+ WERROR werr;
+ struct dcerpc_binding_handle *b;
+ const char *dcname;
+ void *buffer;
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_netlogon,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_netr_GetDcName(b, talloc_tos(),
+ r->in.server_name,
+ r->in.domain_name,
+ &dcname,
+ &werr);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ if (NetApiBufferAllocate(strlen_m_term(dcname), &buffer)) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+ memcpy(buffer, dcname, strlen_m_term(dcname));
+ *r->out.buffer = buffer;
+ done:
+
+ return werr;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR NetGetAnyDCName_l(struct libnetapi_ctx *ctx,
+ struct NetGetAnyDCName *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGetAnyDCName);
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR NetGetAnyDCName_r(struct libnetapi_ctx *ctx,
+ struct NetGetAnyDCName *r)
+{
+ NTSTATUS status;
+ WERROR werr;
+ struct dcerpc_binding_handle *b;
+ const char *dcname;
+ void *buffer;
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_netlogon,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_netr_GetAnyDCName(b, talloc_tos(),
+ r->in.server_name,
+ r->in.domain_name,
+ &dcname,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ if (NetApiBufferAllocate(strlen_m_term(dcname), &buffer)) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+ memcpy(buffer, dcname, strlen_m_term(dcname));
+ *r->out.buffer = buffer;
+
+ done:
+
+ return werr;
+
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR DsGetDcName_l(struct libnetapi_ctx *ctx,
+ struct DsGetDcName *r)
+{
+ NTSTATUS status;
+ struct libnetapi_private_ctx *priv;
+
+ priv = talloc_get_type_abort(ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ status = dsgetdcname(ctx,
+ priv->msg_ctx,
+ r->in.domain_name,
+ r->in.domain_guid,
+ r->in.site_name,
+ r->in.flags,
+ (struct netr_DsRGetDCNameInfo **)r->out.dc_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ libnetapi_set_error_string(ctx,
+ "failed to find DC: %s",
+ get_friendly_nt_error_msg(status));
+ }
+
+ return ntstatus_to_werror(status);
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR DsGetDcName_r(struct libnetapi_ctx *ctx,
+ struct DsGetDcName *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct dcerpc_binding_handle *b;
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_netlogon,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_netr_DsRGetDCNameEx(b,
+ ctx,
+ r->in.server_name,
+ r->in.domain_name,
+ r->in.domain_guid,
+ r->in.site_name,
+ r->in.flags,
+ (struct netr_DsRGetDCNameInfo **)r->out.dc_info,
+ &werr);
+ if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_netr_DsRGetDCName(b,
+ ctx,
+ r->in.server_name,
+ r->in.domain_name,
+ r->in.domain_guid,
+ NULL,
+ r->in.flags,
+ (struct netr_DsRGetDCNameInfo **)r->out.dc_info,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ return werr;
+}
diff --git a/source3/lib/netapi/group.c b/source3/lib/netapi/group.c
new file mode 100644
index 0000000..5258549
--- /dev/null
+++ b/source3/lib/netapi/group.c
@@ -0,0 +1,1848 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Group Support
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+#include "rpc_client/rpc_client.h"
+#include "../librpc/gen_ndr/ndr_samr_c.h"
+#include "rpc_client/init_lsa.h"
+#include "../libcli/security/security.h"
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
+ struct NetGroupAdd *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+ struct policy_handle connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_group_name;
+ struct dom_sid2 *domain_sid = NULL;
+ uint32_t rid = 0;
+ struct dcerpc_binding_handle *b = NULL;
+
+ struct GROUP_INFO_0 *info0 = NULL;
+ struct GROUP_INFO_1 *info1 = NULL;
+ struct GROUP_INFO_2 *info2 = NULL;
+ struct GROUP_INFO_3 *info3 = NULL;
+ union samr_GroupInfo info;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ info0 = (struct GROUP_INFO_0 *)r->in.buffer;
+ break;
+ case 1:
+ info1 = (struct GROUP_INFO_1 *)r->in.buffer;
+ break;
+ case 2:
+ info2 = (struct GROUP_INFO_2 *)r->in.buffer;
+ break;
+ case 3:
+ info3 = (struct GROUP_INFO_3 *)r->in.buffer;
+ break;
+ default:
+ werr = WERR_INVALID_LEVEL;
+ goto done;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_CREATE_GROUP |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ init_lsa_String(&lsa_group_name, info0->grpi0_name);
+ break;
+ case 1:
+ init_lsa_String(&lsa_group_name, info1->grpi1_name);
+ break;
+ case 2:
+ init_lsa_String(&lsa_group_name, info2->grpi2_name);
+ break;
+ case 3:
+ init_lsa_String(&lsa_group_name, info3->grpi3_name);
+ break;
+ }
+
+ status = dcerpc_samr_CreateDomainGroup(b, talloc_tos(),
+ &domain_handle,
+ &lsa_group_name,
+ SEC_STD_DELETE |
+ SAMR_GROUP_ACCESS_SET_INFO,
+ &group_handle,
+ &rid,
+ &result);
+
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ switch (r->in.level) {
+ case 1:
+ if (info1->grpi1_comment) {
+ init_lsa_String(&info.description,
+ info1->grpi1_comment);
+
+ status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFODESCRIPTION,
+ &info,
+ &result);
+ }
+ break;
+ case 2:
+ if (info2->grpi2_comment) {
+ init_lsa_String(&info.description,
+ info2->grpi2_comment);
+
+ status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFODESCRIPTION,
+ &info,
+ &result);
+ if (any_nt_status_not_ok(
+ status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto failed;
+ }
+ }
+
+ if (info2->grpi2_attributes != 0) {
+ info.attributes.attributes = info2->grpi2_attributes;
+ status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &info,
+ &result);
+
+ }
+ break;
+ case 3:
+ if (info3->grpi3_comment) {
+ init_lsa_String(&info.description,
+ info3->grpi3_comment);
+
+ status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFODESCRIPTION,
+ &info,
+ &result);
+ if (any_nt_status_not_ok(
+ status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto failed;
+ }
+ }
+
+ if (info3->grpi3_attributes != 0) {
+ info.attributes.attributes = info3->grpi3_attributes;
+ status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &info,
+ &result);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto failed;
+ }
+
+ werr = WERR_OK;
+ goto done;
+
+ failed:
+ dcerpc_samr_DeleteDomainGroup(b, talloc_tos(),
+ &group_handle, &result);
+
+ done:
+ if (is_valid_policy_hnd(&group_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
+ struct NetGroupAdd *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
+ struct NetGroupDel *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+ struct policy_handle connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_group_name;
+ struct dom_sid2 *domain_sid = NULL;
+ int i = 0;
+ struct dcerpc_binding_handle *b = NULL;
+
+ struct samr_Ids rids;
+ struct samr_Ids types;
+ union samr_GroupInfo *info = NULL;
+ struct samr_RidAttrArray *rid_array = NULL;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_group_name, r->in.group_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_group_name,
+ &rids,
+ &types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ if (types.ids[0] != SID_NAME_DOM_GRP) {
+ werr = WERR_INVALID_DATATYPE;
+ goto done;
+ }
+
+ status = dcerpc_samr_OpenGroup(b, talloc_tos(),
+ &domain_handle,
+ SEC_STD_DELETE |
+ SAMR_GROUP_ACCESS_GET_MEMBERS |
+ SAMR_GROUP_ACCESS_REMOVE_MEMBER |
+ SAMR_GROUP_ACCESS_ADD_MEMBER |
+ SAMR_GROUP_ACCESS_LOOKUP_INFO,
+ rids.ids[0],
+ &group_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &info,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+#if 0
+ /* breaks against NT4 */
+ if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
+ werr = WERR_ACCESS_DENIED;
+ goto done;
+ }
+#endif
+ status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
+ &group_handle,
+ &rid_array,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ {
+ struct lsa_Strings names;
+ struct samr_Ids member_types;
+
+ status = dcerpc_samr_LookupRids(b, talloc_tos(),
+ &domain_handle,
+ rid_array->count,
+ rid_array->rids,
+ &names,
+ &member_types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (names.count != rid_array->count) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (member_types.count != rid_array->count) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ }
+
+ for (i=0; i < rid_array->count; i++) {
+
+ status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
+ &group_handle,
+ rid_array->rids[i],
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ status = dcerpc_samr_DeleteDomainGroup(b, talloc_tos(),
+ &group_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ ZERO_STRUCT(group_handle);
+
+ werr = WERR_OK;
+
+ done:
+ if (is_valid_policy_hnd(&group_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
+ struct NetGroupDel *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetGroupSetInfo *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+ struct policy_handle connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_group_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct dcerpc_binding_handle *b = NULL;
+
+ struct samr_Ids rids;
+ struct samr_Ids types;
+ union samr_GroupInfo info;
+ struct GROUP_INFO_0 *g0;
+ struct GROUP_INFO_1 *g1;
+ struct GROUP_INFO_2 *g2;
+ struct GROUP_INFO_3 *g3;
+ struct GROUP_INFO_1002 *g1002;
+ struct GROUP_INFO_1005 *g1005;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_group_name, r->in.group_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_group_name,
+ &rids,
+ &types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ if (types.ids[0] != SID_NAME_DOM_GRP) {
+ werr = WERR_INVALID_DATATYPE;
+ goto done;
+ }
+
+ status = dcerpc_samr_OpenGroup(b, talloc_tos(),
+ &domain_handle,
+ SAMR_GROUP_ACCESS_SET_INFO |
+ SAMR_GROUP_ACCESS_LOOKUP_INFO,
+ rids.ids[0],
+ &group_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ g0 = (struct GROUP_INFO_0 *)r->in.buffer;
+ init_lsa_String(&info.name, g0->grpi0_name);
+ status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFONAME,
+ &info,
+ &result);
+ break;
+ case 1:
+ g1 = (struct GROUP_INFO_1 *)r->in.buffer;
+ init_lsa_String(&info.description, g1->grpi1_comment);
+ status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFODESCRIPTION,
+ &info,
+ &result);
+ break;
+ case 2:
+ g2 = (struct GROUP_INFO_2 *)r->in.buffer;
+ init_lsa_String(&info.description, g2->grpi2_comment);
+ status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFODESCRIPTION,
+ &info,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ info.attributes.attributes = g2->grpi2_attributes;
+ status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &info,
+ &result);
+ break;
+ case 3:
+ g3 = (struct GROUP_INFO_3 *)r->in.buffer;
+ init_lsa_String(&info.description, g3->grpi3_comment);
+ status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFODESCRIPTION,
+ &info,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ info.attributes.attributes = g3->grpi3_attributes;
+ status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &info,
+ &result);
+ break;
+ case 1002:
+ g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
+ init_lsa_String(&info.description, g1002->grpi1002_comment);
+ status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFODESCRIPTION,
+ &info,
+ &result);
+ break;
+ case 1005:
+ g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
+ info.attributes.attributes = g1005->grpi1005_attributes;
+ status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &info,
+ &result);
+ break;
+ default:
+ status = NT_STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (is_valid_policy_hnd(&group_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetGroupSetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ struct samr_GroupInfoAll *info,
+ struct dom_sid2 *domain_sid,
+ uint32_t rid,
+ uint8_t **buffer)
+{
+ struct GROUP_INFO_0 info0;
+ struct GROUP_INFO_1 info1;
+ struct GROUP_INFO_2 info2;
+ struct GROUP_INFO_3 info3;
+ struct dom_sid sid;
+
+ switch (level) {
+ case 0:
+ info0.grpi0_name = info->name.string;
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
+
+ break;
+ case 1:
+ info1.grpi1_name = info->name.string;
+ info1.grpi1_comment = info->description.string;
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
+
+ break;
+ case 2:
+ info2.grpi2_name = info->name.string;
+ info2.grpi2_comment = info->description.string;
+ info2.grpi2_group_id = rid;
+ info2.grpi2_attributes = info->attributes;
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
+
+ break;
+ case 3:
+ if (!sid_compose(&sid, domain_sid, rid)) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ info3.grpi3_name = info->name.string;
+ info3.grpi3_comment = info->description.string;
+ info3.grpi3_attributes = info->attributes;
+ info3.grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
+
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ W_ERROR_HAVE_NO_MEMORY(*buffer);
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetGroupGetInfo *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+ struct policy_handle connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_group_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct dcerpc_binding_handle *b = NULL;
+
+ struct samr_Ids rids;
+ struct samr_Ids types;
+ union samr_GroupInfo *info = NULL;
+ bool group_info_all = false;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_group_name, r->in.group_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_group_name,
+ &rids,
+ &types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ if (types.ids[0] != SID_NAME_DOM_GRP) {
+ werr = WERR_INVALID_DATATYPE;
+ goto done;
+ }
+
+ status = dcerpc_samr_OpenGroup(b, talloc_tos(),
+ &domain_handle,
+ SAMR_GROUP_ACCESS_LOOKUP_INFO,
+ rids.ids[0],
+ &group_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFOALL2,
+ &info,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS)) {
+ status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFOALL,
+ &info,
+ &result);
+ group_info_all = true;
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ if (!NT_STATUS_IS_OK(result)) {
+ werr = ntstatus_to_werror(result);
+ goto done;
+ }
+
+ werr = map_group_info_to_buffer(ctx, r->in.level,
+ group_info_all ? &info->all : &info->all2,
+ domain_sid, rids.ids[0],
+ r->out.buffer);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+ done:
+ if (is_valid_policy_hnd(&group_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetGroupGetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
+ struct NetGroupAddUser *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+ struct policy_handle connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_group_name, lsa_user_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct dcerpc_binding_handle *b = NULL;
+
+ struct samr_Ids rids;
+ struct samr_Ids types;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_group_name, r->in.group_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_group_name,
+ &rids,
+ &types,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (!NT_STATUS_IS_OK(result)) {
+ werr = WERR_NERR_GROUPNOTFOUND;
+ goto done;
+ }
+ if (rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ if (types.ids[0] != SID_NAME_DOM_GRP) {
+ werr = WERR_NERR_GROUPNOTFOUND;
+ goto done;
+ }
+
+ status = dcerpc_samr_OpenGroup(b, talloc_tos(),
+ &domain_handle,
+ SAMR_GROUP_ACCESS_ADD_MEMBER,
+ rids.ids[0],
+ &group_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ init_lsa_String(&lsa_user_name, r->in.user_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_user_name,
+ &rids,
+ &types,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (!NT_STATUS_IS_OK(result)) {
+ werr = WERR_NERR_USERNOTFOUND;
+ goto done;
+ }
+ if (rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ if (types.ids[0] != SID_NAME_USER) {
+ werr = WERR_NERR_USERNOTFOUND;
+ goto done;
+ }
+
+ status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
+ &group_handle,
+ rids.ids[0],
+ 7, /* why ? */
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (is_valid_policy_hnd(&group_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
+ struct NetGroupAddUser *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
+ struct NetGroupDelUser *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+ struct policy_handle connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_group_name, lsa_user_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct dcerpc_binding_handle *b = NULL;
+
+ struct samr_Ids rids;
+ struct samr_Ids types;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_group_name, r->in.group_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_group_name,
+ &rids,
+ &types,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (!NT_STATUS_IS_OK(result)) {
+ werr = WERR_NERR_GROUPNOTFOUND;
+ goto done;
+ }
+ if (rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ if (types.ids[0] != SID_NAME_DOM_GRP) {
+ werr = WERR_NERR_GROUPNOTFOUND;
+ goto done;
+ }
+
+ status = dcerpc_samr_OpenGroup(b, talloc_tos(),
+ &domain_handle,
+ SAMR_GROUP_ACCESS_REMOVE_MEMBER,
+ rids.ids[0],
+ &group_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ init_lsa_String(&lsa_user_name, r->in.user_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_user_name,
+ &rids,
+ &types,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!NT_STATUS_IS_OK(result)) {
+ werr = WERR_NERR_USERNOTFOUND;
+ goto done;
+ }
+ if (rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ if (types.ids[0] != SID_NAME_USER) {
+ werr = WERR_NERR_USERNOTFOUND;
+ goto done;
+ }
+
+ status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
+ &group_handle,
+ rids.ids[0],
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (is_valid_policy_hnd(&group_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
+ struct NetGroupDelUser *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
+ struct samr_DispInfoFullGroups *groups,
+ uint8_t **buffer)
+{
+ struct GROUP_INFO_0 *g0;
+ int i;
+
+ g0 = talloc_zero_array(mem_ctx, struct GROUP_INFO_0, groups->count);
+ W_ERROR_HAVE_NO_MEMORY(g0);
+
+ for (i=0; i<groups->count; i++) {
+ g0[i].grpi0_name = talloc_strdup(mem_ctx,
+ groups->entries[i].account_name.string);
+ W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
+ }
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
+ sizeof(struct GROUP_INFO_0) * groups->count);
+ W_ERROR_HAVE_NO_MEMORY(*buffer);
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
+ struct samr_DispInfoFullGroups *groups,
+ uint8_t **buffer)
+{
+ struct GROUP_INFO_1 *g1;
+ int i;
+
+ g1 = talloc_zero_array(mem_ctx, struct GROUP_INFO_1, groups->count);
+ W_ERROR_HAVE_NO_MEMORY(g1);
+
+ for (i=0; i<groups->count; i++) {
+ g1[i].grpi1_name = talloc_strdup(mem_ctx,
+ groups->entries[i].account_name.string);
+ g1[i].grpi1_comment = talloc_strdup(mem_ctx,
+ groups->entries[i].description.string);
+ W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
+ }
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
+ sizeof(struct GROUP_INFO_1) * groups->count);
+ W_ERROR_HAVE_NO_MEMORY(*buffer);
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
+ struct samr_DispInfoFullGroups *groups,
+ uint8_t **buffer)
+{
+ struct GROUP_INFO_2 *g2;
+ int i;
+
+ g2 = talloc_zero_array(mem_ctx, struct GROUP_INFO_2, groups->count);
+ W_ERROR_HAVE_NO_MEMORY(g2);
+
+ for (i=0; i<groups->count; i++) {
+ g2[i].grpi2_name = talloc_strdup(mem_ctx,
+ groups->entries[i].account_name.string);
+ g2[i].grpi2_comment = talloc_strdup(mem_ctx,
+ groups->entries[i].description.string);
+ g2[i].grpi2_group_id = groups->entries[i].rid;
+ g2[i].grpi2_attributes = groups->entries[i].acct_flags;
+ W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
+ }
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
+ sizeof(struct GROUP_INFO_2) * groups->count);
+ W_ERROR_HAVE_NO_MEMORY(*buffer);
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
+ struct samr_DispInfoFullGroups *groups,
+ const struct dom_sid *domain_sid,
+ uint8_t **buffer)
+{
+ struct GROUP_INFO_3 *g3;
+ int i;
+
+ g3 = talloc_zero_array(mem_ctx, struct GROUP_INFO_3, groups->count);
+ W_ERROR_HAVE_NO_MEMORY(g3);
+
+ for (i=0; i<groups->count; i++) {
+
+ struct dom_sid sid;
+
+ if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ g3[i].grpi3_name = talloc_strdup(mem_ctx,
+ groups->entries[i].account_name.string);
+ g3[i].grpi3_comment = talloc_strdup(mem_ctx,
+ groups->entries[i].description.string);
+ g3[i].grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
+ g3[i].grpi3_attributes = groups->entries[i].acct_flags;
+ W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
+ }
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
+ sizeof(struct GROUP_INFO_3) * groups->count);
+ W_ERROR_HAVE_NO_MEMORY(*buffer);
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ struct samr_DispInfoFullGroups *groups,
+ const struct dom_sid *domain_sid,
+ uint32_t *entries_read,
+ uint8_t **buffer)
+{
+ if (entries_read) {
+ *entries_read = groups->count;
+ }
+
+ switch (level) {
+ case 0:
+ return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
+ case 1:
+ return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
+ case 2:
+ return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
+ case 3:
+ return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
+ struct NetGroupEnum *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ struct policy_handle domain_handle;
+ union samr_DispInfo info;
+ union samr_DomainInfo *domain_info = NULL;
+ struct dcerpc_binding_handle *b = NULL;
+
+ uint32_t total_size = 0;
+ uint32_t returned_size = 0;
+
+ NTSTATUS result = NT_STATUS_OK;
+ NTSTATUS status;
+ WERROR werr, tmp_werr;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
+ SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
+ &domain_handle,
+ 2,
+ &domain_info,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (r->out.total_entries) {
+ *r->out.total_entries = domain_info->general.num_groups;
+ }
+
+ status = dcerpc_samr_QueryDisplayInfo2(b,
+ ctx,
+ &domain_handle,
+ 3,
+ r->in.resume_handle ?
+ *r->in.resume_handle : 0,
+ (uint32_t)-1,
+ r->in.prefmaxlen,
+ &total_size,
+ &returned_size,
+ &info,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = ntstatus_to_werror(result);
+ if (NT_STATUS_IS_ERR(result)) {
+ goto done;
+ }
+
+ if (r->out.resume_handle && info.info3.count > 0) {
+ *r->out.resume_handle =
+ info.info3.entries[info.info3.count-1].idx;
+ }
+
+ tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
+ r->in.level,
+ &info.info3,
+ domain_sid,
+ r->out.entries_read,
+ r->out.buffer);
+ if (!W_ERROR_IS_OK(tmp_werr)) {
+ werr = tmp_werr;
+ goto done;
+ }
+
+ done:
+ /* if last query */
+ if (NT_STATUS_IS_OK(result) ||
+ NT_STATUS_IS_ERR(result)) {
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
+ struct NetGroupEnum *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
+ struct NetGroupGetUsers *r)
+{
+ /* FIXME: this call needs to cope with large replies */
+
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct samr_Ids group_rids, name_types;
+ struct samr_RidAttrArray *rid_array = NULL;
+ struct lsa_Strings names;
+ struct samr_Ids member_types;
+ struct dcerpc_binding_handle *b = NULL;
+
+ int i;
+ uint32_t entries_read = 0;
+
+ NTSTATUS status;
+ NTSTATUS result = NT_STATUS_OK;
+ WERROR werr;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ *r->out.buffer = NULL;
+ *r->out.entries_read = 0;
+ *r->out.total_entries = 0;
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.group_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &group_rids,
+ &name_types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (group_rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (name_types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ status = dcerpc_samr_OpenGroup(b, talloc_tos(),
+ &domain_handle,
+ SAMR_GROUP_ACCESS_GET_MEMBERS,
+ group_rids.ids[0],
+ &group_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
+ &group_handle,
+ &rid_array,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = dcerpc_samr_LookupRids(b, talloc_tos(),
+ &domain_handle,
+ rid_array->count,
+ rid_array->rids,
+ &names,
+ &member_types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (names.count != rid_array->count) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (member_types.count != rid_array->count) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ for (i=0; i < names.count; i++) {
+
+ if (member_types.ids[i] != SID_NAME_USER) {
+ continue;
+ }
+
+ status = add_GROUP_USERS_INFO_X_buffer(ctx,
+ r->in.level,
+ names.names[i].string,
+ 7,
+ r->out.buffer,
+ &entries_read);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ *r->out.entries_read = entries_read;
+ *r->out.total_entries = entries_read;
+
+ werr = WERR_OK;
+
+ done:
+ if (is_valid_policy_hnd(&group_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
+ struct NetGroupGetUsers *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
+ struct NetGroupSetUsers *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ union samr_GroupInfo *group_info = NULL;
+ struct samr_Ids user_rids, name_types;
+ struct samr_Ids group_rids, group_types;
+ struct samr_RidAttrArray *rid_array = NULL;
+ struct lsa_String *lsa_names = NULL;
+ struct dcerpc_binding_handle *b = NULL;
+
+ uint32_t *add_rids = NULL;
+ uint32_t *del_rids = NULL;
+ size_t num_add_rids = 0;
+ size_t num_del_rids = 0;
+
+ uint32_t *member_rids = NULL;
+
+ struct GROUP_USERS_INFO_0 *i0 = NULL;
+ struct GROUP_USERS_INFO_1 *i1 = NULL;
+
+ int i, k;
+
+ NTSTATUS status;
+ NTSTATUS result = NT_STATUS_OK;
+ WERROR werr;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.group_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &group_rids,
+ &group_types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (group_rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (group_types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ status = dcerpc_samr_OpenGroup(b, talloc_tos(),
+ &domain_handle,
+ SAMR_GROUP_ACCESS_GET_MEMBERS |
+ SAMR_GROUP_ACCESS_ADD_MEMBER |
+ SAMR_GROUP_ACCESS_REMOVE_MEMBER |
+ SAMR_GROUP_ACCESS_LOOKUP_INFO,
+ group_rids.ids[0],
+ &group_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &group_info,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
+ break;
+ case 1:
+ i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
+ break;
+ }
+
+ lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
+ if (!lsa_names) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ for (i=0; i < r->in.num_entries; i++) {
+
+ switch (r->in.level) {
+ case 0:
+ init_lsa_String(&lsa_names[i], i0->grui0_name);
+ i0++;
+ break;
+ case 1:
+ init_lsa_String(&lsa_names[i], i1->grui1_name);
+ i1++;
+ break;
+ }
+ }
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ r->in.num_entries,
+ lsa_names,
+ &user_rids,
+ &name_types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (r->in.num_entries != user_rids.count) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (r->in.num_entries != name_types.count) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ member_rids = user_rids.ids;
+
+ status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
+ &group_handle,
+ &rid_array,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ /* add list */
+
+ for (i=0; i < r->in.num_entries; i++) {
+ bool already_member = false;
+ for (k=0; k < rid_array->count; k++) {
+ if (member_rids[i] == rid_array->rids[k]) {
+ already_member = true;
+ break;
+ }
+ }
+ if (!already_member) {
+ if (!add_rid_to_array_unique(ctx,
+ member_rids[i],
+ &add_rids, &num_add_rids)) {
+ werr = WERR_GEN_FAILURE;
+ goto done;
+ }
+ }
+ }
+
+ /* del list */
+
+ for (k=0; k < rid_array->count; k++) {
+ bool keep_member = false;
+ for (i=0; i < r->in.num_entries; i++) {
+ if (member_rids[i] == rid_array->rids[k]) {
+ keep_member = true;
+ break;
+ }
+ }
+ if (!keep_member) {
+ if (!add_rid_to_array_unique(ctx,
+ rid_array->rids[k],
+ &del_rids, &num_del_rids)) {
+ werr = WERR_GEN_FAILURE;
+ goto done;
+ }
+ }
+ }
+
+ /* add list */
+
+ for (i=0; i < num_add_rids; i++) {
+ status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
+ &group_handle,
+ add_rids[i],
+ 7 /* ? */,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ /* del list */
+
+ for (i=0; i < num_del_rids; i++) {
+ status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
+ &group_handle,
+ del_rids[i],
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (is_valid_policy_hnd(&group_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
+ struct NetGroupSetUsers *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);
+}
diff --git a/source3/lib/netapi/joindomain.c b/source3/lib/netapi/joindomain.c
new file mode 100644
index 0000000..ced1603
--- /dev/null
+++ b/source3/lib/netapi/joindomain.c
@@ -0,0 +1,943 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Join Support
+ * Copyright (C) Guenther Deschner 2007-2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "ads.h"
+#include "librpc/gen_ndr/libnetapi.h"
+#include "libcli/auth/libcli_auth.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+#include "librpc/gen_ndr/libnet_join.h"
+#include "libnet/libnet_join.h"
+#include "../librpc/gen_ndr/ndr_wkssvc_c.h"
+#include "rpc_client/cli_pipe.h"
+#include "secrets.h"
+#include "libsmb/dsgetdcname.h"
+#include "../librpc/gen_ndr/ndr_ODJ.h"
+#include "lib/util/base64.h"
+#include "libnet/libnet_join_offline.h"
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
+ struct NetJoinDomain *r)
+{
+ struct libnet_JoinCtx *j = NULL;
+ struct libnetapi_private_ctx *priv;
+ WERROR werr;
+
+ priv = talloc_get_type_abort(mem_ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ if (!r->in.domain) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ werr = libnet_init_JoinCtx(mem_ctx, &j);
+ W_ERROR_NOT_OK_RETURN(werr);
+
+ j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
+ W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
+
+ if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
+ NTSTATUS status;
+ struct netr_DsRGetDCNameInfo *info = NULL;
+ const char *dc = NULL;
+ uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
+ DS_WRITABLE_REQUIRED |
+ DS_RETURN_DNS_NAME;
+ status = dsgetdcname(mem_ctx, priv->msg_ctx, r->in.domain,
+ NULL, NULL, flags, &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ libnetapi_set_error_string(mem_ctx,
+ "%s", get_friendly_nt_error_msg(status));
+ return ntstatus_to_werror(status);
+ }
+
+ dc = strip_hostname(info->dc_unc);
+ j->in.dc_name = talloc_strdup(mem_ctx, dc);
+ W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
+ }
+
+ if (r->in.account_ou) {
+ j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
+ W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
+ }
+
+ if (r->in.account) {
+ j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
+ W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
+ }
+
+ if (r->in.password) {
+ j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
+ W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
+ }
+
+ j->in.join_flags = r->in.join_flags;
+ j->in.modify_config = true;
+ j->in.debug = true;
+
+ werr = libnet_Join(mem_ctx, j);
+ if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
+ libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
+ }
+ TALLOC_FREE(j);
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
+ struct NetJoinDomain *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct wkssvc_PasswordBuffer *encrypted_password = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ unsigned int old_timeout = 0;
+ struct dcerpc_binding_handle *b;
+ DATA_BLOB session_key;
+
+ if (IS_DC) {
+ return WERR_NERR_SETUPDOMAINCONTROLLER;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server,
+ &ndr_table_wkssvc,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ if (r->in.password) {
+
+ status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = encode_wkssvc_join_password_buffer(ctx,
+ r->in.password,
+ &session_key,
+ &encrypted_password);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+ }
+
+ old_timeout = rpccli_set_timeout(pipe_cli, 600000);
+
+ status = dcerpc_wkssvc_NetrJoinDomain2(b, talloc_tos(),
+ r->in.server,
+ r->in.domain,
+ r->in.account_ou,
+ r->in.account,
+ encrypted_password,
+ r->in.join_flags,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ if (pipe_cli && old_timeout) {
+ rpccli_set_timeout(pipe_cli, old_timeout);
+ }
+
+ return werr;
+}
+/****************************************************************
+****************************************************************/
+
+WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
+ struct NetUnjoinDomain *r)
+{
+ struct libnet_UnjoinCtx *u = NULL;
+ struct dom_sid domain_sid;
+ const char *domain = NULL;
+ WERROR werr;
+ struct libnetapi_private_ctx *priv;
+ const char *realm = lp_realm();
+
+ priv = talloc_get_type_abort(mem_ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
+ return WERR_NERR_SETUPNOTJOINED;
+ }
+
+ werr = libnet_init_UnjoinCtx(mem_ctx, &u);
+ W_ERROR_NOT_OK_RETURN(werr);
+
+ if (realm[0] != '\0') {
+ domain = realm;
+ } else {
+ domain = lp_workgroup();
+ }
+
+ if (r->in.server_name) {
+ u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
+ W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
+ } else {
+ NTSTATUS status;
+ struct netr_DsRGetDCNameInfo *info = NULL;
+ const char *dc = NULL;
+ uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
+ DS_WRITABLE_REQUIRED |
+ DS_RETURN_DNS_NAME;
+ status = dsgetdcname(mem_ctx, priv->msg_ctx, domain,
+ NULL, NULL, flags, &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ libnetapi_set_error_string(mem_ctx,
+ "failed to find DC for domain %s: %s",
+ domain,
+ get_friendly_nt_error_msg(status));
+ return ntstatus_to_werror(status);
+ }
+
+ dc = strip_hostname(info->dc_unc);
+ u->in.dc_name = talloc_strdup(mem_ctx, dc);
+ W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
+
+ u->in.domain_name = domain;
+ }
+
+ if (r->in.account) {
+ u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
+ W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
+ }
+
+ if (r->in.password) {
+ u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
+ W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
+ }
+
+ u->in.domain_name = domain;
+ u->in.unjoin_flags = r->in.unjoin_flags;
+ u->in.delete_machine_account = false;
+ u->in.modify_config = true;
+ u->in.debug = true;
+
+ u->in.domain_sid = &domain_sid;
+
+ werr = libnet_Unjoin(mem_ctx, u);
+ if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
+ libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
+ }
+ TALLOC_FREE(u);
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
+ struct NetUnjoinDomain *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct wkssvc_PasswordBuffer *encrypted_password = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ unsigned int old_timeout = 0;
+ struct dcerpc_binding_handle *b;
+ DATA_BLOB session_key;
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_wkssvc,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ if (r->in.password) {
+
+ status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = encode_wkssvc_join_password_buffer(ctx,
+ r->in.password,
+ &session_key,
+ &encrypted_password);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+ }
+
+ old_timeout = rpccli_set_timeout(pipe_cli, 60000);
+
+ status = dcerpc_wkssvc_NetrUnjoinDomain2(b, talloc_tos(),
+ r->in.server_name,
+ r->in.account,
+ encrypted_password,
+ r->in.unjoin_flags,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ if (pipe_cli && old_timeout) {
+ rpccli_set_timeout(pipe_cli, old_timeout);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
+ struct NetGetJoinInformation *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ const char *buffer = NULL;
+ struct dcerpc_binding_handle *b;
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_wkssvc,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ status = dcerpc_wkssvc_NetrGetJoinInformation(b, talloc_tos(),
+ r->in.server_name,
+ &buffer,
+ (enum wkssvc_NetJoinStatus *)r->out.name_type,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ *r->out.name_buffer = talloc_strdup(ctx, buffer);
+ W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
+ struct NetGetJoinInformation *r)
+{
+ const char *realm = lp_realm();
+
+ if ((lp_security() == SEC_ADS) && realm[0] != '\0') {
+ *r->out.name_buffer = talloc_strdup(ctx, realm);
+ } else {
+ *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
+ }
+ if (!*r->out.name_buffer) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ switch (lp_server_role()) {
+ case ROLE_DOMAIN_MEMBER:
+ case ROLE_DOMAIN_PDC:
+ case ROLE_DOMAIN_BDC:
+ case ROLE_IPA_DC:
+ *r->out.name_type = NetSetupDomainName;
+ break;
+ case ROLE_STANDALONE:
+ default:
+ *r->out.name_type = NetSetupWorkgroupName;
+ break;
+ }
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
+ struct NetGetJoinableOUs *r)
+{
+#ifdef HAVE_ADS
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ WERROR ret;
+ NTSTATUS status;
+ ADS_STATUS ads_status;
+ ADS_STRUCT *ads = NULL;
+ struct netr_DsRGetDCNameInfo *info = NULL;
+ const char *dc = NULL;
+ uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
+ DS_RETURN_DNS_NAME;
+ struct libnetapi_private_ctx *priv;
+ char **p;
+ size_t s;
+
+ priv = talloc_get_type_abort(ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ status = dsgetdcname(tmp_ctx, priv->msg_ctx, r->in.domain,
+ NULL, NULL, flags, &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ libnetapi_set_error_string(ctx, "%s",
+ get_friendly_nt_error_msg(status));
+ ret = ntstatus_to_werror(status);
+ goto out;
+ }
+
+ dc = strip_hostname(info->dc_unc);
+
+ ads = ads_init(tmp_ctx,
+ info->domain_name,
+ info->domain_name,
+ dc,
+ ADS_SASL_PLAIN);
+ if (!ads) {
+ ret = WERR_GEN_FAILURE;
+ goto out;
+ }
+
+ TALLOC_FREE(ads->auth.user_name);
+ if (r->in.account) {
+ ads->auth.user_name = talloc_strdup(ads, r->in.account);
+ if (ads->auth.user_name == NULL) {
+ ret = WERR_NOT_ENOUGH_MEMORY;
+ goto out;
+ }
+ } else {
+ const char *username = NULL;
+
+ libnetapi_get_username(ctx, &username);
+ if (username != NULL) {
+ ads->auth.user_name = talloc_strdup(ads, username);
+ if (ads->auth.user_name == NULL) {
+ ret = WERR_NOT_ENOUGH_MEMORY;
+ goto out;
+ }
+ }
+ }
+
+ TALLOC_FREE(ads->auth.password);
+ if (r->in.password) {
+ ads->auth.password = talloc_strdup(ads, r->in.password);
+ if (ads->auth.password == NULL) {
+ ret = WERR_NOT_ENOUGH_MEMORY;
+ goto out;
+ }
+ } else {
+ const char *password = NULL;
+
+ libnetapi_get_password(ctx, &password);
+ if (password != NULL) {
+ ads->auth.password = talloc_strdup(ads, password);
+ if (ads->auth.password == NULL) {
+ ret = WERR_NOT_ENOUGH_MEMORY;
+ goto out;
+ }
+ }
+ }
+
+ ads_status = ads_connect_user_creds(ads);
+ if (!ADS_ERR_OK(ads_status)) {
+ ret = WERR_NERR_DEFAULTJOINREQUIRED;
+ goto out;
+ }
+
+ ads_status = ads_get_joinable_ous(ads, ctx, &p, &s);
+ if (!ADS_ERR_OK(ads_status)) {
+ ret = WERR_NERR_DEFAULTJOINREQUIRED;
+ goto out;
+ }
+ *r->out.ous = discard_const_p(const char *, p);
+ *r->out.ou_count = s;
+
+ ret = WERR_OK;
+out:
+ TALLOC_FREE(tmp_ctx);
+
+ return ret;
+#else
+ return WERR_NOT_SUPPORTED;
+#endif
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
+ struct NetGetJoinableOUs *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct wkssvc_PasswordBuffer *encrypted_password = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ struct dcerpc_binding_handle *b;
+ DATA_BLOB session_key;
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_wkssvc,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ if (r->in.password) {
+
+ status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = encode_wkssvc_join_password_buffer(ctx,
+ r->in.password,
+ &session_key,
+ &encrypted_password);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+ }
+
+ status = dcerpc_wkssvc_NetrGetJoinableOus2(b, talloc_tos(),
+ r->in.server_name,
+ r->in.domain,
+ r->in.account,
+ encrypted_password,
+ r->out.ou_count,
+ r->out.ous,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
+ struct NetRenameMachineInDomain *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct wkssvc_PasswordBuffer *encrypted_password = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ struct dcerpc_binding_handle *b;
+ DATA_BLOB session_key;
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_wkssvc,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ if (r->in.password) {
+
+ status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = encode_wkssvc_join_password_buffer(ctx,
+ r->in.password,
+ &session_key,
+ &encrypted_password);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+ }
+
+ status = dcerpc_wkssvc_NetrRenameMachineInDomain2(b, talloc_tos(),
+ r->in.server_name,
+ r->in.new_machine_name,
+ r->in.account,
+ encrypted_password,
+ r->in.rename_options,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
+ struct NetRenameMachineInDomain *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRenameMachineInDomain);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetProvisionComputerAccount_r(struct libnetapi_ctx *ctx,
+ struct NetProvisionComputerAccount *r)
+{
+ return NetProvisionComputerAccount_l(ctx, r);
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR NetProvisionComputerAccount_backend(struct libnetapi_ctx *ctx,
+ struct NetProvisionComputerAccount *r,
+ TALLOC_CTX *mem_ctx,
+ struct ODJ_PROVISION_DATA **p)
+{
+ WERROR werr;
+ struct libnet_JoinCtx *j = NULL;
+ int use_kerberos = 0;
+ const char *username = NULL;
+
+ werr = libnet_init_JoinCtx(mem_ctx, &j);
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ j->in.domain_name = talloc_strdup(j, r->in.domain);
+ if (j->in.domain_name == NULL) {
+ talloc_free(j);
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ talloc_free(discard_const_p(char *, j->in.machine_name));
+ j->in.machine_name = talloc_strdup(j, r->in.machine_name);
+ if (j->in.machine_name == NULL) {
+ talloc_free(j);
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ if (r->in.dcname) {
+ j->in.dc_name = talloc_strdup(j, r->in.dcname);
+ if (j->in.dc_name == NULL) {
+ talloc_free(j);
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+ }
+
+ if (r->in.machine_account_ou) {
+ j->in.account_ou = talloc_strdup(j, r->in.machine_account_ou);
+ if (j->in.account_ou == NULL) {
+ talloc_free(j);
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+ }
+
+ libnetapi_get_username(ctx, &username);
+ if (username == NULL) {
+ talloc_free(j);
+ return WERR_NERR_BADUSERNAME;
+ }
+
+ j->in.admin_account = talloc_strdup(j, username);
+ if (j->in.admin_account == NULL) {
+ talloc_free(j);
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ libnetapi_get_use_kerberos(ctx, &use_kerberos);
+ if (!use_kerberos) {
+ const char *password = NULL;
+
+ libnetapi_get_password(ctx, &password);
+ if (password == NULL) {
+ talloc_free(j);
+ return WERR_NERR_BADPASSWORD;
+ }
+ j->in.admin_password = talloc_strdup(j, password);
+ if (j->in.admin_password == NULL) {
+ talloc_free(j);
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+ }
+
+ j->in.use_kerberos = use_kerberos;
+ j->in.debug = true;
+ j->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
+ WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE;
+
+ if (r->in.options & NETSETUP_PROVISION_REUSE_ACCOUNT) {
+ j->in.join_flags |= WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
+ }
+
+ if (r->in.options & NETSETUP_PROVISION_USE_DEFAULT_PASSWORD) {
+ j->in.join_flags |= WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED;
+ j->in.machine_password = talloc_strdup(j, r->in.machine_name);
+ if (j->in.machine_password == NULL) {
+ talloc_free(j);
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+ }
+
+ j->in.provision_computer_account_only = true;
+
+ werr = libnet_Join(mem_ctx, j);
+ if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
+ libnetapi_set_error_string(ctx, "%s", j->out.error_string);
+ talloc_free(j);
+ return werr;
+ }
+
+ werr = libnet_odj_compose_ODJ_PROVISION_DATA(mem_ctx, j, p);
+ if (!W_ERROR_IS_OK(werr)) {
+ talloc_free(j);
+ return werr;
+ }
+
+ TALLOC_FREE(j);
+
+ return WERR_OK;
+}
+
+WERROR NetProvisionComputerAccount_l(struct libnetapi_ctx *ctx,
+ struct NetProvisionComputerAccount *r)
+{
+ WERROR werr;
+ enum ndr_err_code ndr_err;
+ const char *b64_bin_data_str;
+ DATA_BLOB blob;
+ struct ODJ_PROVISION_DATA_serialized_ptr odj_provision_data;
+ struct ODJ_PROVISION_DATA *p;
+ TALLOC_CTX *mem_ctx = talloc_new(ctx);
+
+ if (r->in.provision_bin_data == NULL &&
+ r->in.provision_text_data == NULL) {
+ return WERR_INVALID_PARAMETER;
+ }
+ if (r->in.provision_bin_data != NULL &&
+ r->in.provision_text_data != NULL) {
+ return WERR_INVALID_PARAMETER;
+ }
+ if (r->in.provision_bin_data == NULL &&
+ r->in.provision_bin_data_size != NULL) {
+ return WERR_INVALID_PARAMETER;
+ }
+ if (r->in.provision_bin_data != NULL &&
+ r->in.provision_bin_data_size == NULL) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ if (r->in.domain == NULL) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ if (r->in.machine_name == NULL) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ werr = NetProvisionComputerAccount_backend(ctx, r, mem_ctx, &p);
+ if (!W_ERROR_IS_OK(werr)) {
+ talloc_free(mem_ctx);
+ return werr;
+ }
+
+ ZERO_STRUCT(odj_provision_data);
+
+ odj_provision_data.s.p = p;
+
+ ndr_err = ndr_push_struct_blob(&blob, ctx, &odj_provision_data,
+ (ndr_push_flags_fn_t)ndr_push_ODJ_PROVISION_DATA_serialized_ptr);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ talloc_free(mem_ctx);
+ return W_ERROR(NERR_BadOfflineJoinInfo);
+ }
+
+ talloc_free(mem_ctx);
+
+ if (r->out.provision_text_data != NULL) {
+ b64_bin_data_str = base64_encode_data_blob(ctx, blob);
+ if (b64_bin_data_str == NULL) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+ *r->out.provision_text_data = b64_bin_data_str;
+ }
+
+ if (r->out.provision_bin_data != NULL &&
+ r->out.provision_bin_data_size != NULL) {
+ *r->out.provision_bin_data = blob.data;
+ *r->out.provision_bin_data_size = blob.length;
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetRequestOfflineDomainJoin_r(struct libnetapi_ctx *ctx,
+ struct NetRequestOfflineDomainJoin *r)
+{
+ return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR NetRequestOfflineDomainJoin_backend(struct libnetapi_ctx *ctx,
+ const struct ODJ_WIN7BLOB *win7blob,
+ const struct ODJ_PROVISION_DATA *odj_provision_data)
+{
+ struct libnet_JoinCtx *j = NULL;
+ WERROR werr;
+
+ werr = libnet_init_JoinCtx(ctx, &j);
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ j->in.domain_name = talloc_strdup(j, win7blob->lpDomain);
+ if (j->in.domain_name == NULL) {
+ talloc_free(j);
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ talloc_free(discard_const_p(char *, j->in.machine_name));
+ j->in.machine_name = talloc_strdup(j, win7blob->lpMachineName);
+ if (j->in.machine_name == NULL) {
+ talloc_free(j);
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ j->in.machine_password = talloc_strdup(j, win7blob->lpMachinePassword);
+ if (j->in.machine_password == NULL) {
+ talloc_free(j);
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ j->in.request_offline_join = true;
+ j->in.odj_provision_data = discard_const(odj_provision_data);
+ j->in.debug = true;
+ j->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
+ WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED;
+
+ werr = libnet_Join(j, j);
+ if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
+ libnetapi_set_error_string(ctx, "%s", j->out.error_string);
+ talloc_free(j);
+ return werr;
+ }
+
+ TALLOC_FREE(j);
+
+ return WERR_OK;
+}
+
+WERROR NetRequestOfflineDomainJoin_l(struct libnetapi_ctx *ctx,
+ struct NetRequestOfflineDomainJoin *r)
+{
+ DATA_BLOB blob, blob_base64;
+ enum ndr_err_code ndr_err;
+ struct ODJ_PROVISION_DATA_serialized_ptr odj_provision_data;
+ bool ok;
+ struct ODJ_WIN7BLOB win7blob = { 0 };
+ WERROR werr;
+
+ if (r->in.provision_bin_data == NULL ||
+ r->in.provision_bin_data_size == 0) {
+ return W_ERROR(NERR_NoOfflineJoinInfo);
+ }
+
+ if (r->in.provision_bin_data_size < 2) {
+ return W_ERROR(NERR_BadOfflineJoinInfo);
+ }
+
+ if (r->in.provision_bin_data[0] == 0xff &&
+ r->in.provision_bin_data[1] == 0xfe) {
+ ok = convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX,
+ r->in.provision_bin_data+2,
+ r->in.provision_bin_data_size-2,
+ &blob_base64.data,
+ &blob_base64.length);
+ if (!ok) {
+ return W_ERROR(NERR_BadOfflineJoinInfo);
+ }
+ } else {
+ blob_base64 = data_blob(r->in.provision_bin_data,
+ r->in.provision_bin_data_size);
+ }
+
+ blob = base64_decode_data_blob_talloc(ctx, (const char *)blob_base64.data);
+
+ ndr_err = ndr_pull_struct_blob(&blob, ctx, &odj_provision_data,
+ (ndr_pull_flags_fn_t)ndr_pull_ODJ_PROVISION_DATA_serialized_ptr);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return W_ERROR(NERR_BadOfflineJoinInfo);
+ }
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_DEBUG(ODJ_PROVISION_DATA_serialized_ptr, &odj_provision_data);
+ }
+
+ if (odj_provision_data.s.p->ulVersion != 1) {
+ return W_ERROR(NERR_ProvisioningBlobUnsupported);
+ }
+
+ werr = libnet_odj_find_win7blob(odj_provision_data.s.p, &win7blob);
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ if (!(r->in.options & NETSETUP_PROVISION_ONLINE_CALLER)) {
+ return WERR_NERR_SETUPNOTJOINED;
+ }
+
+ werr = NetRequestOfflineDomainJoin_backend(ctx,
+ &win7blob,
+ odj_provision_data.s.p);
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ return W_ERROR(NERR_JoinPerformedMustRestart);
+}
diff --git a/source3/lib/netapi/libnetapi.c b/source3/lib/netapi/libnetapi.c
new file mode 100644
index 0000000..2fd97bb
--- /dev/null
+++ b/source3/lib/netapi/libnetapi.c
@@ -0,0 +1,2952 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Support
+ * Copyright (C) Guenther Deschner 2007-2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+#include "librpc/gen_ndr/ndr_libnetapi.h"
+
+/****************************************************************
+ NetJoinDomain
+****************************************************************/
+
+NET_API_STATUS NetJoinDomain(const char * server /* [in] [unique] */,
+ const char * domain /* [in] [ref] */,
+ const char * account_ou /* [in] [unique] */,
+ const char * account /* [in] [unique] */,
+ const char * password /* [in] [unique] */,
+ uint32_t join_flags /* [in] */)
+{
+ struct NetJoinDomain r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server = server;
+ r.in.domain = domain;
+ r.in.account_ou = account_ou;
+ r.in.account = account;
+ r.in.password = password;
+ r.in.join_flags = join_flags;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetJoinDomain, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server)) {
+ werr = NetJoinDomain_l(ctx, &r);
+ } else {
+ werr = NetJoinDomain_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetJoinDomain, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetUnjoinDomain
+****************************************************************/
+
+NET_API_STATUS NetUnjoinDomain(const char * server_name /* [in] [unique] */,
+ const char * account /* [in] [unique] */,
+ const char * password /* [in] [unique] */,
+ uint32_t unjoin_flags /* [in] */)
+{
+ struct NetUnjoinDomain r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.account = account;
+ r.in.password = password;
+ r.in.unjoin_flags = unjoin_flags;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUnjoinDomain, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUnjoinDomain_l(ctx, &r);
+ } else {
+ werr = NetUnjoinDomain_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUnjoinDomain, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetGetJoinInformation
+****************************************************************/
+
+NET_API_STATUS NetGetJoinInformation(const char * server_name /* [in] [unique] */,
+ const char * *name_buffer /* [out] [ref] */,
+ uint16_t *name_type /* [out] [ref] */)
+{
+ struct NetGetJoinInformation r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+
+ /* Out parameters */
+ r.out.name_buffer = name_buffer;
+ r.out.name_type = name_type;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGetJoinInformation, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGetJoinInformation_l(ctx, &r);
+ } else {
+ werr = NetGetJoinInformation_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGetJoinInformation, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetGetJoinableOUs
+****************************************************************/
+
+NET_API_STATUS NetGetJoinableOUs(const char * server_name /* [in] [unique] */,
+ const char * domain /* [in] [ref] */,
+ const char * account /* [in] [unique] */,
+ const char * password /* [in] [unique] */,
+ uint32_t *ou_count /* [out] [ref] */,
+ const char * **ous /* [out] [ref] */)
+{
+ struct NetGetJoinableOUs r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.domain = domain;
+ r.in.account = account;
+ r.in.password = password;
+
+ /* Out parameters */
+ r.out.ou_count = ou_count;
+ r.out.ous = ous;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGetJoinableOUs, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGetJoinableOUs_l(ctx, &r);
+ } else {
+ werr = NetGetJoinableOUs_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGetJoinableOUs, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetRenameMachineInDomain
+****************************************************************/
+
+NET_API_STATUS NetRenameMachineInDomain(const char * server_name /* [in] */,
+ const char * new_machine_name /* [in] */,
+ const char * account /* [in] */,
+ const char * password /* [in] */,
+ uint32_t rename_options /* [in] */)
+{
+ struct NetRenameMachineInDomain r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.new_machine_name = new_machine_name;
+ r.in.account = account;
+ r.in.password = password;
+ r.in.rename_options = rename_options;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetRenameMachineInDomain, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetRenameMachineInDomain_l(ctx, &r);
+ } else {
+ werr = NetRenameMachineInDomain_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetRenameMachineInDomain, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetProvisionComputerAccount
+****************************************************************/
+
+NET_API_STATUS NetProvisionComputerAccount(const char * domain /* [in] [ref] */,
+ const char * machine_name /* [in] [ref] */,
+ const char * machine_account_ou /* [in] [unique] */,
+ const char * dcname /* [in] [unique] */,
+ uint32_t options /* [in] */,
+ uint8_t **provision_bin_data /* [in,out] [unique] */,
+ uint32_t *provision_bin_data_size /* [in,out] [unique] */,
+ const char * *provision_text_data /* [in,out] [unique] */)
+{
+ struct NetProvisionComputerAccount r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.domain = domain;
+ r.in.machine_name = machine_name;
+ r.in.machine_account_ou = machine_account_ou;
+ r.in.dcname = dcname;
+ r.in.options = options;
+ r.in.provision_bin_data = provision_bin_data;
+ r.in.provision_bin_data_size = provision_bin_data_size;
+ r.in.provision_text_data = provision_text_data;
+
+ /* Out parameters */
+ r.out.provision_bin_data = provision_bin_data;
+ r.out.provision_bin_data_size = provision_bin_data_size;
+ r.out.provision_text_data = provision_text_data;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetProvisionComputerAccount, &r);
+ }
+
+ werr = NetProvisionComputerAccount_l(ctx, &r);
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetProvisionComputerAccount, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetRequestOfflineDomainJoin
+****************************************************************/
+
+NET_API_STATUS NetRequestOfflineDomainJoin(uint8_t *provision_bin_data /* [in] [unique] */,
+ uint32_t provision_bin_data_size /* [in] */,
+ uint32_t options /* [in] */,
+ const char * windows_path /* [in] [unique] */)
+{
+ struct NetRequestOfflineDomainJoin r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.provision_bin_data = provision_bin_data;
+ r.in.provision_bin_data_size = provision_bin_data_size;
+ r.in.options = options;
+ r.in.windows_path = windows_path;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetRequestOfflineDomainJoin, &r);
+ }
+
+ werr = NetRequestOfflineDomainJoin_l(ctx, &r);
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetRequestOfflineDomainJoin, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetServerGetInfo
+****************************************************************/
+
+NET_API_STATUS NetServerGetInfo(const char * server_name /* [in] [unique] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetServerGetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetServerGetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetServerGetInfo_l(ctx, &r);
+ } else {
+ werr = NetServerGetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetServerGetInfo, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetServerSetInfo
+****************************************************************/
+
+NET_API_STATUS NetServerSetInfo(const char * server_name /* [in] [unique] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_error /* [out] [ref] */)
+{
+ struct NetServerSetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_error = parm_error;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetServerSetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetServerSetInfo_l(ctx, &r);
+ } else {
+ werr = NetServerSetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetServerSetInfo, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetWkstaGetInfo
+****************************************************************/
+
+NET_API_STATUS NetWkstaGetInfo(const char * server_name /* [in] [unique] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetWkstaGetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetWkstaGetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetWkstaGetInfo_l(ctx, &r);
+ } else {
+ werr = NetWkstaGetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetWkstaGetInfo, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetGetDCName
+****************************************************************/
+
+NET_API_STATUS NetGetDCName(const char * server_name /* [in] [unique] */,
+ const char * domain_name /* [in] [unique] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetGetDCName r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.domain_name = domain_name;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGetDCName, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGetDCName_l(ctx, &r);
+ } else {
+ werr = NetGetDCName_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGetDCName, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetGetAnyDCName
+****************************************************************/
+
+NET_API_STATUS NetGetAnyDCName(const char * server_name /* [in] [unique] */,
+ const char * domain_name /* [in] [unique] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetGetAnyDCName r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.domain_name = domain_name;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGetAnyDCName, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGetAnyDCName_l(ctx, &r);
+ } else {
+ werr = NetGetAnyDCName_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGetAnyDCName, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ DsGetDcName
+****************************************************************/
+
+NET_API_STATUS DsGetDcName(const char * server_name /* [in] [unique] */,
+ const char * domain_name /* [in] [ref] */,
+ struct GUID *domain_guid /* [in] [unique] */,
+ const char * site_name /* [in] [unique] */,
+ uint32_t flags /* [in] */,
+ struct DOMAIN_CONTROLLER_INFO **dc_info /* [out] [ref] */)
+{
+ struct DsGetDcName r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.domain_name = domain_name;
+ r.in.domain_guid = domain_guid;
+ r.in.site_name = site_name;
+ r.in.flags = flags;
+
+ /* Out parameters */
+ r.out.dc_info = dc_info;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(DsGetDcName, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = DsGetDcName_l(ctx, &r);
+ } else {
+ werr = DsGetDcName_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(DsGetDcName, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetUserAdd
+****************************************************************/
+
+NET_API_STATUS NetUserAdd(const char * server_name /* [in] [unique] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_error /* [out] [ref] */)
+{
+ struct NetUserAdd r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_error = parm_error;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserAdd, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserAdd_l(ctx, &r);
+ } else {
+ werr = NetUserAdd_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserAdd, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetUserDel
+****************************************************************/
+
+NET_API_STATUS NetUserDel(const char * server_name /* [in] [unique] */,
+ const char * user_name /* [in] [ref] */)
+{
+ struct NetUserDel r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.user_name = user_name;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserDel, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserDel_l(ctx, &r);
+ } else {
+ werr = NetUserDel_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserDel, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetUserEnum
+****************************************************************/
+
+NET_API_STATUS NetUserEnum(const char * server_name /* [in] [unique] */,
+ uint32_t level /* [in] */,
+ uint32_t filter /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */)
+{
+ struct NetUserEnum r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.filter = filter;
+ r.in.prefmaxlen = prefmaxlen;
+ r.in.resume_handle = resume_handle;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+ r.out.resume_handle = resume_handle;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserEnum, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserEnum_l(ctx, &r);
+ } else {
+ werr = NetUserEnum_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserEnum, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetUserChangePassword
+****************************************************************/
+
+NET_API_STATUS NetUserChangePassword(const char * domain_name /* [in] */,
+ const char * user_name /* [in] */,
+ const char * old_password /* [in] */,
+ const char * new_password /* [in] */)
+{
+ struct NetUserChangePassword r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.domain_name = domain_name;
+ r.in.user_name = user_name;
+ r.in.old_password = old_password;
+ r.in.new_password = new_password;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserChangePassword, &r);
+ }
+
+ werr = NetUserChangePassword_l(ctx, &r);
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserChangePassword, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetUserGetInfo
+****************************************************************/
+
+NET_API_STATUS NetUserGetInfo(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetUserGetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.user_name = user_name;
+ r.in.level = level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserGetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserGetInfo_l(ctx, &r);
+ } else {
+ werr = NetUserGetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserGetInfo, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetUserSetInfo
+****************************************************************/
+
+NET_API_STATUS NetUserSetInfo(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetUserSetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.user_name = user_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserSetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserSetInfo_l(ctx, &r);
+ } else {
+ werr = NetUserSetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserSetInfo, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetUserGetGroups
+****************************************************************/
+
+NET_API_STATUS NetUserGetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */)
+{
+ struct NetUserGetGroups r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.user_name = user_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserGetGroups, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserGetGroups_l(ctx, &r);
+ } else {
+ werr = NetUserGetGroups_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserGetGroups, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetUserSetGroups
+****************************************************************/
+
+NET_API_STATUS NetUserSetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t num_entries /* [in] */)
+{
+ struct NetUserSetGroups r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.user_name = user_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+ r.in.num_entries = num_entries;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserSetGroups, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserSetGroups_l(ctx, &r);
+ } else {
+ werr = NetUserSetGroups_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserSetGroups, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetUserGetLocalGroups
+****************************************************************/
+
+NET_API_STATUS NetUserGetLocalGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint32_t flags /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */)
+{
+ struct NetUserGetLocalGroups r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.user_name = user_name;
+ r.in.level = level;
+ r.in.flags = flags;
+ r.in.prefmaxlen = prefmaxlen;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserGetLocalGroups, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserGetLocalGroups_l(ctx, &r);
+ } else {
+ werr = NetUserGetLocalGroups_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserGetLocalGroups, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetUserModalsGet
+****************************************************************/
+
+NET_API_STATUS NetUserModalsGet(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetUserModalsGet r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserModalsGet, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserModalsGet_l(ctx, &r);
+ } else {
+ werr = NetUserModalsGet_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserModalsGet, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetUserModalsSet
+****************************************************************/
+
+NET_API_STATUS NetUserModalsSet(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetUserModalsSet r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserModalsSet, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserModalsSet_l(ctx, &r);
+ } else {
+ werr = NetUserModalsSet_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserModalsSet, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetQueryDisplayInformation
+****************************************************************/
+
+NET_API_STATUS NetQueryDisplayInformation(const char * server_name /* [in] [unique] */,
+ uint32_t level /* [in] */,
+ uint32_t idx /* [in] */,
+ uint32_t entries_requested /* [in] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ void **buffer /* [out] [noprint,ref] */)
+{
+ struct NetQueryDisplayInformation r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.idx = idx;
+ r.in.entries_requested = entries_requested;
+ r.in.prefmaxlen = prefmaxlen;
+
+ /* Out parameters */
+ r.out.entries_read = entries_read;
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetQueryDisplayInformation, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetQueryDisplayInformation_l(ctx, &r);
+ } else {
+ werr = NetQueryDisplayInformation_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetQueryDisplayInformation, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetGroupAdd
+****************************************************************/
+
+NET_API_STATUS NetGroupAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetGroupAdd r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupAdd, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupAdd_l(ctx, &r);
+ } else {
+ werr = NetGroupAdd_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupAdd, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetGroupDel
+****************************************************************/
+
+NET_API_STATUS NetGroupDel(const char * server_name /* [in] */,
+ const char * group_name /* [in] */)
+{
+ struct NetGroupDel r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupDel, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupDel_l(ctx, &r);
+ } else {
+ werr = NetGroupDel_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupDel, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetGroupEnum
+****************************************************************/
+
+NET_API_STATUS NetGroupEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */)
+{
+ struct NetGroupEnum r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+ r.in.resume_handle = resume_handle;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+ r.out.resume_handle = resume_handle;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupEnum, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupEnum_l(ctx, &r);
+ } else {
+ werr = NetGroupEnum_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupEnum, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetGroupSetInfo
+****************************************************************/
+
+NET_API_STATUS NetGroupSetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetGroupSetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupSetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupSetInfo_l(ctx, &r);
+ } else {
+ werr = NetGroupSetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupSetInfo, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetGroupGetInfo
+****************************************************************/
+
+NET_API_STATUS NetGroupGetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetGroupGetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupGetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupGetInfo_l(ctx, &r);
+ } else {
+ werr = NetGroupGetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupGetInfo, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetGroupAddUser
+****************************************************************/
+
+NET_API_STATUS NetGroupAddUser(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ const char * user_name /* [in] */)
+{
+ struct NetGroupAddUser r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.user_name = user_name;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupAddUser, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupAddUser_l(ctx, &r);
+ } else {
+ werr = NetGroupAddUser_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupAddUser, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetGroupDelUser
+****************************************************************/
+
+NET_API_STATUS NetGroupDelUser(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ const char * user_name /* [in] */)
+{
+ struct NetGroupDelUser r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.user_name = user_name;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupDelUser, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupDelUser_l(ctx, &r);
+ } else {
+ werr = NetGroupDelUser_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupDelUser, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetGroupGetUsers
+****************************************************************/
+
+NET_API_STATUS NetGroupGetUsers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */)
+{
+ struct NetGroupGetUsers r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+ r.in.resume_handle = resume_handle;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+ r.out.resume_handle = resume_handle;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupGetUsers, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupGetUsers_l(ctx, &r);
+ } else {
+ werr = NetGroupGetUsers_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupGetUsers, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetGroupSetUsers
+****************************************************************/
+
+NET_API_STATUS NetGroupSetUsers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t num_entries /* [in] */)
+{
+ struct NetGroupSetUsers r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+ r.in.num_entries = num_entries;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupSetUsers, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupSetUsers_l(ctx, &r);
+ } else {
+ werr = NetGroupSetUsers_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupSetUsers, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupAdd
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetLocalGroupAdd r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupAdd, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupAdd_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupAdd_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupAdd, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupDel
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupDel(const char * server_name /* [in] */,
+ const char * group_name /* [in] */)
+{
+ struct NetLocalGroupDel r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupDel, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupDel_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupDel_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupDel, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupGetInfo
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupGetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetLocalGroupGetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupGetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupGetInfo_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupGetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupGetInfo, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupSetInfo
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupSetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetLocalGroupSetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupSetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupSetInfo_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupSetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupSetInfo, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupEnum
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */)
+{
+ struct NetLocalGroupEnum r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+ r.in.resume_handle = resume_handle;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+ r.out.resume_handle = resume_handle;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupEnum, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupEnum_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupEnum_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupEnum, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupAddMembers
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupAddMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */)
+{
+ struct NetLocalGroupAddMembers r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+ r.in.total_entries = total_entries;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupAddMembers, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupAddMembers_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupAddMembers_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupAddMembers, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupDelMembers
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupDelMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */)
+{
+ struct NetLocalGroupDelMembers r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+ r.in.total_entries = total_entries;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupDelMembers, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupDelMembers_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupDelMembers_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupDelMembers, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupGetMembers
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupGetMembers(const char * server_name /* [in] */,
+ const char * local_group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */)
+{
+ struct NetLocalGroupGetMembers r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.local_group_name = local_group_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+ r.in.resume_handle = resume_handle;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+ r.out.resume_handle = resume_handle;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupGetMembers, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupGetMembers_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupGetMembers_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupGetMembers, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupSetMembers
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupSetMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */)
+{
+ struct NetLocalGroupSetMembers r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+ r.in.total_entries = total_entries;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupSetMembers, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupSetMembers_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupSetMembers_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupSetMembers, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetRemoteTOD
+****************************************************************/
+
+NET_API_STATUS NetRemoteTOD(const char * server_name /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetRemoteTOD r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetRemoteTOD, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetRemoteTOD_l(ctx, &r);
+ } else {
+ werr = NetRemoteTOD_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetRemoteTOD, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetShareAdd
+****************************************************************/
+
+NET_API_STATUS NetShareAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetShareAdd r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetShareAdd, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetShareAdd_l(ctx, &r);
+ } else {
+ werr = NetShareAdd_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetShareAdd, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetShareDel
+****************************************************************/
+
+NET_API_STATUS NetShareDel(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t reserved /* [in] */)
+{
+ struct NetShareDel r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.net_name = net_name;
+ r.in.reserved = reserved;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetShareDel, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetShareDel_l(ctx, &r);
+ } else {
+ werr = NetShareDel_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetShareDel, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetShareEnum
+****************************************************************/
+
+NET_API_STATUS NetShareEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */)
+{
+ struct NetShareEnum r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+ r.in.resume_handle = resume_handle;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+ r.out.resume_handle = resume_handle;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetShareEnum, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetShareEnum_l(ctx, &r);
+ } else {
+ werr = NetShareEnum_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetShareEnum, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetShareGetInfo
+****************************************************************/
+
+NET_API_STATUS NetShareGetInfo(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetShareGetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.net_name = net_name;
+ r.in.level = level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetShareGetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetShareGetInfo_l(ctx, &r);
+ } else {
+ werr = NetShareGetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetShareGetInfo, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetShareSetInfo
+****************************************************************/
+
+NET_API_STATUS NetShareSetInfo(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetShareSetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.net_name = net_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetShareSetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetShareSetInfo_l(ctx, &r);
+ } else {
+ werr = NetShareSetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetShareSetInfo, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetFileClose
+****************************************************************/
+
+NET_API_STATUS NetFileClose(const char * server_name /* [in] */,
+ uint32_t fileid /* [in] */)
+{
+ struct NetFileClose r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.fileid = fileid;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetFileClose, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetFileClose_l(ctx, &r);
+ } else {
+ werr = NetFileClose_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetFileClose, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetFileGetInfo
+****************************************************************/
+
+NET_API_STATUS NetFileGetInfo(const char * server_name /* [in] */,
+ uint32_t fileid /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetFileGetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.fileid = fileid;
+ r.in.level = level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetFileGetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetFileGetInfo_l(ctx, &r);
+ } else {
+ werr = NetFileGetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetFileGetInfo, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetFileEnum
+****************************************************************/
+
+NET_API_STATUS NetFileEnum(const char * server_name /* [in] */,
+ const char * base_path /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */)
+{
+ struct NetFileEnum r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.base_path = base_path;
+ r.in.user_name = user_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+ r.in.resume_handle = resume_handle;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+ r.out.resume_handle = resume_handle;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetFileEnum, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetFileEnum_l(ctx, &r);
+ } else {
+ werr = NetFileEnum_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetFileEnum, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetShutdownInit
+****************************************************************/
+
+NET_API_STATUS NetShutdownInit(const char * server_name /* [in] */,
+ const char * message /* [in] */,
+ uint32_t timeout /* [in] */,
+ uint8_t force_apps /* [in] */,
+ uint8_t do_reboot /* [in] */)
+{
+ struct NetShutdownInit r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.message = message;
+ r.in.timeout = timeout;
+ r.in.force_apps = force_apps;
+ r.in.do_reboot = do_reboot;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetShutdownInit, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetShutdownInit_l(ctx, &r);
+ } else {
+ werr = NetShutdownInit_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetShutdownInit, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ NetShutdownAbort
+****************************************************************/
+
+NET_API_STATUS NetShutdownAbort(const char * server_name /* [in] */)
+{
+ struct NetShutdownAbort r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetShutdownAbort, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetShutdownAbort_l(ctx, &r);
+ } else {
+ werr = NetShutdownAbort_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetShutdownAbort, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ I_NetLogonControl
+****************************************************************/
+
+NET_API_STATUS I_NetLogonControl(const char * server_name /* [in] */,
+ uint32_t function_code /* [in] */,
+ uint32_t query_level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct I_NetLogonControl r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.function_code = function_code;
+ r.in.query_level = query_level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(I_NetLogonControl, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = I_NetLogonControl_l(ctx, &r);
+ } else {
+ werr = I_NetLogonControl_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(I_NetLogonControl, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
+/****************************************************************
+ I_NetLogonControl2
+****************************************************************/
+
+NET_API_STATUS I_NetLogonControl2(const char * server_name /* [in] */,
+ uint32_t function_code /* [in] */,
+ uint32_t query_level /* [in] */,
+ uint8_t *data /* [in] [unique] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct I_NetLogonControl2 r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ZERO_STRUCT(r);
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.function_code = function_code;
+ r.in.query_level = query_level;
+ r.in.data = data;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(I_NetLogonControl2, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = I_NetLogonControl2_l(ctx, &r);
+ } else {
+ werr = I_NetLogonControl2_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(I_NetLogonControl2, &r);
+ }
+
+ TALLOC_FREE(frame);
+ return (NET_API_STATUS)r.out.result;
+}
+
diff --git a/source3/lib/netapi/libnetapi.h b/source3/lib/netapi/libnetapi.h
new file mode 100644
index 0000000..d217656
--- /dev/null
+++ b/source3/lib/netapi/libnetapi.h
@@ -0,0 +1,506 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Support
+ * Copyright (C) Guenther Deschner 2007-2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LIBNETAPI_LIBNETAPI__
+#define __LIBNETAPI_LIBNETAPI__
+NET_API_STATUS NetJoinDomain(const char * server /* [in] [unique] */,
+ const char * domain /* [in] [ref] */,
+ const char * account_ou /* [in] [unique] */,
+ const char * account /* [in] [unique] */,
+ const char * password /* [in] [unique] */,
+ uint32_t join_flags /* [in] */);
+WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
+ struct NetJoinDomain *r);
+WERROR NetJoinDomain_l(struct libnetapi_ctx *ctx,
+ struct NetJoinDomain *r);
+NET_API_STATUS NetUnjoinDomain(const char * server_name /* [in] [unique] */,
+ const char * account /* [in] [unique] */,
+ const char * password /* [in] [unique] */,
+ uint32_t unjoin_flags /* [in] */);
+WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
+ struct NetUnjoinDomain *r);
+WERROR NetUnjoinDomain_l(struct libnetapi_ctx *ctx,
+ struct NetUnjoinDomain *r);
+NET_API_STATUS NetGetJoinInformation(const char * server_name /* [in] [unique] */,
+ const char * *name_buffer /* [out] [ref] */,
+ uint16_t *name_type /* [out] [ref] */);
+WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
+ struct NetGetJoinInformation *r);
+WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
+ struct NetGetJoinInformation *r);
+NET_API_STATUS NetGetJoinableOUs(const char * server_name /* [in] [unique] */,
+ const char * domain /* [in] [ref] */,
+ const char * account /* [in] [unique] */,
+ const char * password /* [in] [unique] */,
+ uint32_t *ou_count /* [out] [ref] */,
+ const char * **ous /* [out] [ref] */);
+WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
+ struct NetGetJoinableOUs *r);
+WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
+ struct NetGetJoinableOUs *r);
+NET_API_STATUS NetRenameMachineInDomain(const char * server_name /* [in] */,
+ const char * new_machine_name /* [in] */,
+ const char * account /* [in] */,
+ const char * password /* [in] */,
+ uint32_t rename_options /* [in] */);
+WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
+ struct NetRenameMachineInDomain *r);
+WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
+ struct NetRenameMachineInDomain *r);
+NET_API_STATUS NetProvisionComputerAccount(const char * domain /* [in] [ref] */,
+ const char * machine_name /* [in] [ref] */,
+ const char * machine_account_ou /* [in] [unique] */,
+ const char * dcname /* [in] [unique] */,
+ uint32_t options /* [in] */,
+ uint8_t **provision_bin_data /* [in,out] [unique] */,
+ uint32_t *provision_bin_data_size /* [in,out] [unique] */,
+ const char * *provision_text_data /* [in,out] [unique] */);
+WERROR NetProvisionComputerAccount_r(struct libnetapi_ctx *ctx,
+ struct NetProvisionComputerAccount *r);
+WERROR NetProvisionComputerAccount_l(struct libnetapi_ctx *ctx,
+ struct NetProvisionComputerAccount *r);
+NET_API_STATUS NetRequestOfflineDomainJoin(uint8_t *provision_bin_data /* [in] [unique] */,
+ uint32_t provision_bin_data_size /* [in] */,
+ uint32_t options /* [in] */,
+ const char * windows_path /* [in] [unique] */);
+WERROR NetRequestOfflineDomainJoin_r(struct libnetapi_ctx *ctx,
+ struct NetRequestOfflineDomainJoin *r);
+WERROR NetRequestOfflineDomainJoin_l(struct libnetapi_ctx *ctx,
+ struct NetRequestOfflineDomainJoin *r);
+NET_API_STATUS NetServerGetInfo(const char * server_name /* [in] [unique] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetServerGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetServerGetInfo *r);
+WERROR NetServerGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetServerGetInfo *r);
+NET_API_STATUS NetServerSetInfo(const char * server_name /* [in] [unique] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_error /* [out] [ref] */);
+WERROR NetServerSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetServerSetInfo *r);
+WERROR NetServerSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetServerSetInfo *r);
+NET_API_STATUS NetWkstaGetInfo(const char * server_name /* [in] [unique] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetWkstaGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetWkstaGetInfo *r);
+WERROR NetWkstaGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetWkstaGetInfo *r);
+NET_API_STATUS NetGetDCName(const char * server_name /* [in] [unique] */,
+ const char * domain_name /* [in] [unique] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetGetDCName_r(struct libnetapi_ctx *ctx,
+ struct NetGetDCName *r);
+WERROR NetGetDCName_l(struct libnetapi_ctx *ctx,
+ struct NetGetDCName *r);
+NET_API_STATUS NetGetAnyDCName(const char * server_name /* [in] [unique] */,
+ const char * domain_name /* [in] [unique] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetGetAnyDCName_r(struct libnetapi_ctx *ctx,
+ struct NetGetAnyDCName *r);
+WERROR NetGetAnyDCName_l(struct libnetapi_ctx *ctx,
+ struct NetGetAnyDCName *r);
+NET_API_STATUS DsGetDcName(const char * server_name /* [in] [unique] */,
+ const char * domain_name /* [in] [ref] */,
+ struct GUID *domain_guid /* [in] [unique] */,
+ const char * site_name /* [in] [unique] */,
+ uint32_t flags /* [in] */,
+ struct DOMAIN_CONTROLLER_INFO **dc_info /* [out] [ref] */);
+WERROR DsGetDcName_r(struct libnetapi_ctx *ctx,
+ struct DsGetDcName *r);
+WERROR DsGetDcName_l(struct libnetapi_ctx *ctx,
+ struct DsGetDcName *r);
+NET_API_STATUS NetUserAdd(const char * server_name /* [in] [unique] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_error /* [out] [ref] */);
+WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
+ struct NetUserAdd *r);
+WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
+ struct NetUserAdd *r);
+NET_API_STATUS NetUserDel(const char * server_name /* [in] [unique] */,
+ const char * user_name /* [in] [ref] */);
+WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
+ struct NetUserDel *r);
+WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
+ struct NetUserDel *r);
+NET_API_STATUS NetUserEnum(const char * server_name /* [in] [unique] */,
+ uint32_t level /* [in] */,
+ uint32_t filter /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
+ struct NetUserEnum *r);
+WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
+ struct NetUserEnum *r);
+NET_API_STATUS NetUserChangePassword(const char * domain_name /* [in] */,
+ const char * user_name /* [in] */,
+ const char * old_password /* [in] */,
+ const char * new_password /* [in] */);
+WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
+ struct NetUserChangePassword *r);
+WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
+ struct NetUserChangePassword *r);
+NET_API_STATUS NetUserGetInfo(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetUserGetInfo *r);
+WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetUserGetInfo *r);
+NET_API_STATUS NetUserSetInfo(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetUserSetInfo *r);
+WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetUserSetInfo *r);
+NET_API_STATUS NetUserGetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */);
+WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
+ struct NetUserGetGroups *r);
+WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
+ struct NetUserGetGroups *r);
+NET_API_STATUS NetUserSetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t num_entries /* [in] */);
+WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx,
+ struct NetUserSetGroups *r);
+WERROR NetUserSetGroups_l(struct libnetapi_ctx *ctx,
+ struct NetUserSetGroups *r);
+NET_API_STATUS NetUserGetLocalGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint32_t flags /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */);
+WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx,
+ struct NetUserGetLocalGroups *r);
+WERROR NetUserGetLocalGroups_l(struct libnetapi_ctx *ctx,
+ struct NetUserGetLocalGroups *r);
+NET_API_STATUS NetUserModalsGet(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
+ struct NetUserModalsGet *r);
+WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
+ struct NetUserModalsGet *r);
+NET_API_STATUS NetUserModalsSet(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
+ struct NetUserModalsSet *r);
+WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
+ struct NetUserModalsSet *r);
+NET_API_STATUS NetQueryDisplayInformation(const char * server_name /* [in] [unique] */,
+ uint32_t level /* [in] */,
+ uint32_t idx /* [in] */,
+ uint32_t entries_requested /* [in] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ void **buffer /* [out] [noprint,ref] */);
+WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
+ struct NetQueryDisplayInformation *r);
+WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
+ struct NetQueryDisplayInformation *r);
+NET_API_STATUS NetGroupAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
+ struct NetGroupAdd *r);
+WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
+ struct NetGroupAdd *r);
+NET_API_STATUS NetGroupDel(const char * server_name /* [in] */,
+ const char * group_name /* [in] */);
+WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
+ struct NetGroupDel *r);
+WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
+ struct NetGroupDel *r);
+NET_API_STATUS NetGroupEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
+ struct NetGroupEnum *r);
+WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
+ struct NetGroupEnum *r);
+NET_API_STATUS NetGroupSetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetGroupSetInfo *r);
+WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetGroupSetInfo *r);
+NET_API_STATUS NetGroupGetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetGroupGetInfo *r);
+WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetGroupGetInfo *r);
+NET_API_STATUS NetGroupAddUser(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ const char * user_name /* [in] */);
+WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
+ struct NetGroupAddUser *r);
+WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
+ struct NetGroupAddUser *r);
+NET_API_STATUS NetGroupDelUser(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ const char * user_name /* [in] */);
+WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
+ struct NetGroupDelUser *r);
+WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
+ struct NetGroupDelUser *r);
+NET_API_STATUS NetGroupGetUsers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
+ struct NetGroupGetUsers *r);
+WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
+ struct NetGroupGetUsers *r);
+NET_API_STATUS NetGroupSetUsers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t num_entries /* [in] */);
+WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
+ struct NetGroupSetUsers *r);
+WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
+ struct NetGroupSetUsers *r);
+NET_API_STATUS NetLocalGroupAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAdd *r);
+WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAdd *r);
+NET_API_STATUS NetLocalGroupDel(const char * server_name /* [in] */,
+ const char * group_name /* [in] */);
+WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDel *r);
+WERROR NetLocalGroupDel_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDel *r);
+NET_API_STATUS NetLocalGroupGetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetInfo *r);
+WERROR NetLocalGroupGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetInfo *r);
+NET_API_STATUS NetLocalGroupSetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetInfo *r);
+WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetInfo *r);
+NET_API_STATUS NetLocalGroupEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupEnum *r);
+WERROR NetLocalGroupEnum_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupEnum *r);
+NET_API_STATUS NetLocalGroupAddMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */);
+WERROR NetLocalGroupAddMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAddMembers *r);
+WERROR NetLocalGroupAddMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAddMembers *r);
+NET_API_STATUS NetLocalGroupDelMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */);
+WERROR NetLocalGroupDelMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDelMembers *r);
+WERROR NetLocalGroupDelMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDelMembers *r);
+NET_API_STATUS NetLocalGroupGetMembers(const char * server_name /* [in] */,
+ const char * local_group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+WERROR NetLocalGroupGetMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetMembers *r);
+WERROR NetLocalGroupGetMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetMembers *r);
+NET_API_STATUS NetLocalGroupSetMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */);
+WERROR NetLocalGroupSetMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetMembers *r);
+WERROR NetLocalGroupSetMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetMembers *r);
+NET_API_STATUS NetRemoteTOD(const char * server_name /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetRemoteTOD_r(struct libnetapi_ctx *ctx,
+ struct NetRemoteTOD *r);
+WERROR NetRemoteTOD_l(struct libnetapi_ctx *ctx,
+ struct NetRemoteTOD *r);
+NET_API_STATUS NetShareAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetShareAdd_r(struct libnetapi_ctx *ctx,
+ struct NetShareAdd *r);
+WERROR NetShareAdd_l(struct libnetapi_ctx *ctx,
+ struct NetShareAdd *r);
+NET_API_STATUS NetShareDel(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t reserved /* [in] */);
+WERROR NetShareDel_r(struct libnetapi_ctx *ctx,
+ struct NetShareDel *r);
+WERROR NetShareDel_l(struct libnetapi_ctx *ctx,
+ struct NetShareDel *r);
+NET_API_STATUS NetShareEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+WERROR NetShareEnum_r(struct libnetapi_ctx *ctx,
+ struct NetShareEnum *r);
+WERROR NetShareEnum_l(struct libnetapi_ctx *ctx,
+ struct NetShareEnum *r);
+NET_API_STATUS NetShareGetInfo(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetShareGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetShareGetInfo *r);
+WERROR NetShareGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetShareGetInfo *r);
+NET_API_STATUS NetShareSetInfo(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetShareSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetShareSetInfo *r);
+WERROR NetShareSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetShareSetInfo *r);
+NET_API_STATUS NetFileClose(const char * server_name /* [in] */,
+ uint32_t fileid /* [in] */);
+WERROR NetFileClose_r(struct libnetapi_ctx *ctx,
+ struct NetFileClose *r);
+WERROR NetFileClose_l(struct libnetapi_ctx *ctx,
+ struct NetFileClose *r);
+NET_API_STATUS NetFileGetInfo(const char * server_name /* [in] */,
+ uint32_t fileid /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetFileGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetFileGetInfo *r);
+WERROR NetFileGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetFileGetInfo *r);
+NET_API_STATUS NetFileEnum(const char * server_name /* [in] */,
+ const char * base_path /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+WERROR NetFileEnum_r(struct libnetapi_ctx *ctx,
+ struct NetFileEnum *r);
+WERROR NetFileEnum_l(struct libnetapi_ctx *ctx,
+ struct NetFileEnum *r);
+NET_API_STATUS NetShutdownInit(const char * server_name /* [in] */,
+ const char * message /* [in] */,
+ uint32_t timeout /* [in] */,
+ uint8_t force_apps /* [in] */,
+ uint8_t do_reboot /* [in] */);
+WERROR NetShutdownInit_r(struct libnetapi_ctx *ctx,
+ struct NetShutdownInit *r);
+WERROR NetShutdownInit_l(struct libnetapi_ctx *ctx,
+ struct NetShutdownInit *r);
+NET_API_STATUS NetShutdownAbort(const char * server_name /* [in] */);
+WERROR NetShutdownAbort_r(struct libnetapi_ctx *ctx,
+ struct NetShutdownAbort *r);
+WERROR NetShutdownAbort_l(struct libnetapi_ctx *ctx,
+ struct NetShutdownAbort *r);
+NET_API_STATUS I_NetLogonControl(const char * server_name /* [in] */,
+ uint32_t function_code /* [in] */,
+ uint32_t query_level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR I_NetLogonControl_r(struct libnetapi_ctx *ctx,
+ struct I_NetLogonControl *r);
+WERROR I_NetLogonControl_l(struct libnetapi_ctx *ctx,
+ struct I_NetLogonControl *r);
+NET_API_STATUS I_NetLogonControl2(const char * server_name /* [in] */,
+ uint32_t function_code /* [in] */,
+ uint32_t query_level /* [in] */,
+ uint8_t *data /* [in] [unique] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR I_NetLogonControl2_r(struct libnetapi_ctx *ctx,
+ struct I_NetLogonControl2 *r);
+WERROR I_NetLogonControl2_l(struct libnetapi_ctx *ctx,
+ struct I_NetLogonControl2 *r);
+#endif /* __LIBNETAPI_LIBNETAPI__ */
diff --git a/source3/lib/netapi/localgroup.c b/source3/lib/netapi/localgroup.c
new file mode 100644
index 0000000..5d6ad17
--- /dev/null
+++ b/source3/lib/netapi/localgroup.c
@@ -0,0 +1,1376 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi LocalGroup Support
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+#include "rpc_client/rpc_client.h"
+#include "../librpc/gen_ndr/ndr_samr_c.h"
+#include "../librpc/gen_ndr/ndr_lsa_c.h"
+#include "rpc_client/cli_lsarpc.h"
+#include "rpc_client/init_lsa.h"
+#include "../libcli/security/security.h"
+
+static NTSTATUS libnetapi_samr_lookup_and_open_alias(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ const char *group_name,
+ uint32_t access_rights,
+ struct policy_handle *alias_handle)
+{
+ NTSTATUS status, result;
+
+ struct lsa_String lsa_account_name;
+ struct samr_Ids user_rids, name_types;
+ struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
+
+ init_lsa_String(&lsa_account_name, group_name);
+
+ status = dcerpc_samr_LookupNames(b, mem_ctx,
+ domain_handle,
+ 1,
+ &lsa_account_name,
+ &user_rids,
+ &name_types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ return status;
+ }
+ if (user_rids.count != 1) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+ if (name_types.count != 1) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
+ switch (name_types.ids[0]) {
+ case SID_NAME_ALIAS:
+ case SID_NAME_WKN_GRP:
+ break;
+ default:
+ return NT_STATUS_INVALID_SID;
+ }
+
+ status = dcerpc_samr_OpenAlias(b, mem_ctx,
+ domain_handle,
+ access_rights,
+ user_rids.ids[0],
+ alias_handle,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ return result;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS libnetapi_samr_open_alias_queryinfo(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *handle,
+ uint32_t rid,
+ uint32_t access_rights,
+ enum samr_AliasInfoEnum level,
+ union samr_AliasInfo **alias_info)
+{
+ NTSTATUS status, result;
+ struct policy_handle alias_handle;
+ union samr_AliasInfo *_alias_info = NULL;
+ struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
+
+ ZERO_STRUCT(alias_handle);
+
+ status = dcerpc_samr_OpenAlias(b, mem_ctx,
+ handle,
+ access_rights,
+ rid,
+ &alias_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ goto done;
+ }
+
+ status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
+ &alias_handle,
+ level,
+ &_alias_info,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ goto done;
+ }
+
+ *alias_info = _alias_info;
+
+ done:
+ if (is_valid_policy_hnd(&alias_handle)) {
+ dcerpc_samr_Close(b, mem_ctx, &alias_handle, &result);
+ }
+
+ return status;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAdd *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+ struct lsa_String lsa_account_name;
+ struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ uint32_t rid;
+ struct dcerpc_binding_handle *b = NULL;
+
+ struct LOCALGROUP_INFO_0 *info0 = NULL;
+ struct LOCALGROUP_INFO_1 *info1 = NULL;
+
+ const char *alias_name = NULL;
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(alias_handle);
+
+ switch (r->in.level) {
+ case 0:
+ info0 = (struct LOCALGROUP_INFO_0 *)r->in.buffer;
+ alias_name = info0->lgrpi0_name;
+ break;
+ case 1:
+ info1 = (struct LOCALGROUP_INFO_1 *)r->in.buffer;
+ alias_name = info1->lgrpi1_name;
+ break;
+ default:
+ werr = WERR_INVALID_LEVEL;
+ goto done;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_LOOKUP_DOMAIN |
+ SAMR_ACCESS_ENUM_DOMAINS,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &builtin_handle,
+ alias_name,
+ SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+ &alias_handle);
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ }
+
+ if (NT_STATUS_IS_OK(status)) {
+ werr = WERR_ALIAS_EXISTS;
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, alias_name);
+
+ status = dcerpc_samr_CreateDomAlias(b, talloc_tos(),
+ &domain_handle,
+ &lsa_account_name,
+ SEC_STD_DELETE |
+ SAMR_ALIAS_ACCESS_SET_INFO,
+ &alias_handle,
+ &rid,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (r->in.level == 1 && info1->lgrpi1_comment) {
+
+ union samr_AliasInfo alias_info;
+
+ init_lsa_String(&alias_info.description, info1->lgrpi1_comment);
+
+ status = dcerpc_samr_SetAliasInfo(b, talloc_tos(),
+ &alias_handle,
+ ALIASINFODESCRIPTION,
+ &alias_info,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (is_valid_policy_hnd(&alias_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAdd *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAdd);
+}
+
+/****************************************************************
+****************************************************************/
+
+
+WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDel *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+ struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ struct dcerpc_binding_handle *b = NULL;
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(alias_handle);
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_LOOKUP_DOMAIN |
+ SAMR_ACCESS_ENUM_DOMAINS,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &builtin_handle,
+ r->in.group_name,
+ SEC_STD_DELETE,
+ &alias_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ }
+
+ if (NT_STATUS_IS_OK(status)) {
+ goto delete_alias;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &domain_handle,
+ r->in.group_name,
+ SEC_STD_DELETE,
+ &alias_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+
+ delete_alias:
+ status = dcerpc_samr_DeleteDomAlias(b, talloc_tos(),
+ &alias_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ ZERO_STRUCT(alias_handle);
+
+ werr = WERR_OK;
+
+ done:
+ if (is_valid_policy_hnd(&alias_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupDel_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDel *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDel);
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR map_alias_info_to_buffer(TALLOC_CTX *mem_ctx,
+ const char *alias_name,
+ struct samr_AliasInfoAll *info,
+ uint32_t level,
+ uint32_t *entries_read,
+ uint8_t **buffer)
+{
+ struct LOCALGROUP_INFO_0 g0;
+ struct LOCALGROUP_INFO_1 g1;
+ struct LOCALGROUP_INFO_1002 g1002;
+
+ switch (level) {
+ case 0:
+ g0.lgrpi0_name = talloc_strdup(mem_ctx, alias_name);
+ W_ERROR_HAVE_NO_MEMORY(g0.lgrpi0_name);
+
+ ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_0, g0,
+ (struct LOCALGROUP_INFO_0 **)buffer, entries_read);
+
+ break;
+ case 1:
+ g1.lgrpi1_name = talloc_strdup(mem_ctx, alias_name);
+ g1.lgrpi1_comment = talloc_strdup(mem_ctx, info->description.string);
+ W_ERROR_HAVE_NO_MEMORY(g1.lgrpi1_name);
+
+ ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1, g1,
+ (struct LOCALGROUP_INFO_1 **)buffer, entries_read);
+
+ break;
+ case 1002:
+ g1002.lgrpi1002_comment = talloc_strdup(mem_ctx, info->description.string);
+
+ ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1002, g1002,
+ (struct LOCALGROUP_INFO_1002 **)buffer, entries_read);
+
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetInfo *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+ struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ union samr_AliasInfo *alias_info = NULL;
+ uint32_t entries_read = 0;
+ struct dcerpc_binding_handle *b = NULL;
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ case 1002:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(alias_handle);
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_LOOKUP_DOMAIN |
+ SAMR_ACCESS_ENUM_DOMAINS,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &builtin_handle,
+ r->in.group_name,
+ SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+ &alias_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ }
+
+ if (NT_STATUS_IS_OK(status)) {
+ goto query_alias;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &domain_handle,
+ r->in.group_name,
+ SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+ &alias_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ query_alias:
+ status = dcerpc_samr_QueryAliasInfo(b, talloc_tos(),
+ &alias_handle,
+ ALIASINFOALL,
+ &alias_info,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = map_alias_info_to_buffer(ctx,
+ r->in.group_name,
+ &alias_info->all,
+ r->in.level, &entries_read,
+ r->out.buffer);
+
+ done:
+ if (is_valid_policy_hnd(&alias_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR map_buffer_to_alias_info(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ uint8_t *buffer,
+ enum samr_AliasInfoEnum *alias_level,
+ union samr_AliasInfo **alias_info)
+{
+ struct LOCALGROUP_INFO_0 *info0;
+ struct LOCALGROUP_INFO_1 *info1;
+ struct LOCALGROUP_INFO_1002 *info1002;
+ union samr_AliasInfo *info = NULL;
+
+ info = talloc_zero(mem_ctx, union samr_AliasInfo);
+ W_ERROR_HAVE_NO_MEMORY(info);
+
+ switch (level) {
+ case 0:
+ info0 = (struct LOCALGROUP_INFO_0 *)buffer;
+ init_lsa_String(&info->name, info0->lgrpi0_name);
+ *alias_level = ALIASINFONAME;
+ break;
+ case 1:
+ info1 = (struct LOCALGROUP_INFO_1 *)buffer;
+ /* group name will be ignored */
+ init_lsa_String(&info->description, info1->lgrpi1_comment);
+ *alias_level = ALIASINFODESCRIPTION;
+ break;
+ case 1002:
+ info1002 = (struct LOCALGROUP_INFO_1002 *)buffer;
+ init_lsa_String(&info->description, info1002->lgrpi1002_comment);
+ *alias_level = ALIASINFODESCRIPTION;
+ break;
+ }
+
+ *alias_info = info;
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetInfo *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+ struct lsa_String lsa_account_name;
+ struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ enum samr_AliasInfoEnum alias_level = 0;
+ union samr_AliasInfo *alias_info = NULL;
+ struct dcerpc_binding_handle *b = NULL;
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ case 1002:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(alias_handle);
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_LOOKUP_DOMAIN |
+ SAMR_ACCESS_ENUM_DOMAINS,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.group_name);
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &builtin_handle,
+ r->in.group_name,
+ SAMR_ALIAS_ACCESS_SET_INFO,
+ &alias_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ }
+
+ if (NT_STATUS_IS_OK(status)) {
+ goto set_alias;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &domain_handle,
+ r->in.group_name,
+ SAMR_ALIAS_ACCESS_SET_INFO,
+ &alias_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ }
+
+ set_alias:
+
+ werr = map_buffer_to_alias_info(ctx, r->in.level, r->in.buffer,
+ &alias_level, &alias_info);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_samr_SetAliasInfo(b, talloc_tos(),
+ &alias_handle,
+ alias_level,
+ alias_info,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (is_valid_policy_hnd(&alias_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupEnum *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+ struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ uint32_t entries_read = 0;
+ union samr_DomainInfo *domain_info = NULL;
+ union samr_DomainInfo *builtin_info = NULL;
+ struct samr_SamArray *domain_sam_array = NULL;
+ struct samr_SamArray *builtin_sam_array = NULL;
+ int i;
+ struct dcerpc_binding_handle *b = NULL;
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ if (r->out.total_entries) {
+ *r->out.total_entries = 0;
+ }
+ if (r->out.entries_read) {
+ *r->out.entries_read = 0;
+ }
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(alias_handle);
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_LOOKUP_DOMAIN |
+ SAMR_ACCESS_ENUM_DOMAINS,
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
+ SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_LOOKUP_DOMAIN |
+ SAMR_ACCESS_ENUM_DOMAINS,
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
+ SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
+ &builtin_handle,
+ 2,
+ &builtin_info,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (r->out.total_entries) {
+ *r->out.total_entries += builtin_info->general.num_aliases;
+ }
+
+ status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
+ &domain_handle,
+ 2,
+ &domain_info,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (r->out.total_entries) {
+ *r->out.total_entries += domain_info->general.num_aliases;
+ }
+
+ status = dcerpc_samr_EnumDomainAliases(b, talloc_tos(),
+ &builtin_handle,
+ r->in.resume_handle,
+ &builtin_sam_array,
+ r->in.prefmaxlen,
+ &entries_read,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ for (i=0; i<builtin_sam_array->count; i++) {
+ union samr_AliasInfo *alias_info = NULL;
+
+ if (r->in.level == 1) {
+
+ status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
+ &builtin_handle,
+ builtin_sam_array->entries[i].idx,
+ SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+ ALIASINFOALL,
+ &alias_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ werr = map_alias_info_to_buffer(ctx,
+ builtin_sam_array->entries[i].name.string,
+ alias_info ? &alias_info->all : NULL,
+ r->in.level,
+ r->out.entries_read,
+ r->out.buffer);
+ }
+
+ status = dcerpc_samr_EnumDomainAliases(b, talloc_tos(),
+ &domain_handle,
+ r->in.resume_handle,
+ &domain_sam_array,
+ r->in.prefmaxlen,
+ &entries_read,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ for (i=0; i<domain_sam_array->count; i++) {
+
+ union samr_AliasInfo *alias_info = NULL;
+
+ if (r->in.level == 1) {
+ status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
+ &domain_handle,
+ domain_sam_array->entries[i].idx,
+ SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+ ALIASINFOALL,
+ &alias_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ werr = map_alias_info_to_buffer(ctx,
+ domain_sam_array->entries[i].name.string,
+ alias_info ? &alias_info->all : NULL,
+ r->in.level,
+ r->out.entries_read,
+ r->out.buffer);
+ }
+
+ done:
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupEnum_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupEnum *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupEnum);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS libnetapi_lsa_lookup_names3(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *lsa_pipe,
+ const char *name,
+ struct dom_sid *sid)
+{
+ NTSTATUS status, result;
+ struct policy_handle lsa_handle;
+ struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
+
+ struct lsa_RefDomainList *domains = NULL;
+ struct lsa_TransSidArray3 sids;
+ uint32_t count = 0;
+
+ struct lsa_String names;
+ uint32_t num_names = 1;
+
+ if (!sid || !name) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ZERO_STRUCT(sids);
+
+ init_lsa_String(&names, name);
+
+ status = rpccli_lsa_open_policy2(lsa_pipe, mem_ctx,
+ false,
+ SEC_STD_READ_CONTROL |
+ LSA_POLICY_VIEW_LOCAL_INFORMATION |
+ LSA_POLICY_LOOKUP_NAMES,
+ &lsa_handle);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ status = dcerpc_lsa_LookupNames3(b, mem_ctx,
+ &lsa_handle,
+ num_names,
+ &names,
+ &domains,
+ &sids,
+ LSA_LOOKUP_NAMES_ALL, /* sure ? */
+ &count,
+ 0, 0,
+ &result);
+ NT_STATUS_NOT_OK_RETURN(status);
+ NT_STATUS_NOT_OK_RETURN(result);
+
+ if (count != 1 || sids.count != 1) {
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
+ sid_copy(sid, sids.sids[0].sid);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAddMembers *add,
+ struct NetLocalGroupDelMembers *del,
+ struct NetLocalGroupSetMembers *set)
+{
+ struct NetLocalGroupAddMembers *r = NULL;
+
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct rpc_pipe_client *lsa_pipe = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+ struct lsa_String lsa_account_name;
+ struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ struct dom_sid *member_sids = NULL;
+ int i = 0, k = 0;
+
+ struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL;
+ struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL;
+
+ struct dom_sid *add_sids = NULL;
+ struct dom_sid *del_sids = NULL;
+ uint32_t num_add_sids = 0;
+ uint32_t num_del_sids = 0;
+ struct dcerpc_binding_handle *b = NULL;
+
+ if ((!add && !del && !set) || (add && del && set)) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ if (add) {
+ r = add;
+ }
+
+ if (del) {
+ r = (struct NetLocalGroupAddMembers *)del;
+ }
+
+ if (set) {
+ r = (struct NetLocalGroupAddMembers *)set;
+ }
+
+ if (r==NULL || r->in.group_name == NULL) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 3:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ if (r->in.total_entries == 0 || !r->in.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(alias_handle);
+
+ member_sids = talloc_zero_array(ctx, struct dom_sid,
+ r->in.total_entries);
+ W_ERROR_HAVE_NO_MEMORY(member_sids);
+
+ switch (r->in.level) {
+ case 0:
+ info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer;
+ for (i=0; i < r->in.total_entries; i++) {
+ sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid);
+ }
+ break;
+ case 3:
+ info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer;
+ break;
+ default:
+ break;
+ }
+
+ if (r->in.level == 3) {
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_lsarpc,
+ &lsa_pipe);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ for (i=0; i < r->in.total_entries; i++) {
+ status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe,
+ info3[i].lgrmi3_domainandname,
+ &member_sids[i]);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+ TALLOC_FREE(lsa_pipe);
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_LOOKUP_DOMAIN |
+ SAMR_ACCESS_ENUM_DOMAINS,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.group_name);
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &builtin_handle,
+ r->in.group_name,
+ SAMR_ALIAS_ACCESS_ADD_MEMBER |
+ SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
+ SAMR_ALIAS_ACCESS_GET_MEMBERS |
+ SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+ &alias_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ }
+
+ if (NT_STATUS_IS_OK(status)) {
+ goto modify_membership;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &domain_handle,
+ r->in.group_name,
+ SAMR_ALIAS_ACCESS_ADD_MEMBER |
+ SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
+ SAMR_ALIAS_ACCESS_GET_MEMBERS |
+ SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+ &alias_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ }
+
+ modify_membership:
+
+ if (add) {
+ for (i=0; i < r->in.total_entries; i++) {
+ status = add_sid_to_array_unique(ctx, &member_sids[i],
+ &add_sids,
+ &num_add_sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+ }
+
+ if (del) {
+ for (i=0; i < r->in.total_entries; i++) {
+ status = add_sid_to_array_unique(ctx, &member_sids[i],
+ &del_sids,
+ &num_del_sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+ }
+
+ if (set) {
+
+ struct lsa_SidArray current_sids;
+
+ status = dcerpc_samr_GetMembersInAlias(b, talloc_tos(),
+ &alias_handle,
+ &current_sids,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ /* add list */
+
+ for (i=0; i < r->in.total_entries; i++) {
+ bool already_member = false;
+ for (k=0; k < current_sids.num_sids; k++) {
+ if (dom_sid_equal(&member_sids[i],
+ current_sids.sids[k].sid)) {
+ already_member = true;
+ break;
+ }
+ }
+ if (!already_member) {
+ status = add_sid_to_array_unique(ctx,
+ &member_sids[i],
+ &add_sids, &num_add_sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+ }
+
+ /* del list */
+
+ for (k=0; k < current_sids.num_sids; k++) {
+ bool keep_member = false;
+ for (i=0; i < r->in.total_entries; i++) {
+ if (dom_sid_equal(&member_sids[i],
+ current_sids.sids[k].sid)) {
+ keep_member = true;
+ break;
+ }
+ }
+ if (!keep_member) {
+ status = add_sid_to_array_unique(ctx,
+ current_sids.sids[k].sid,
+ &del_sids, &num_del_sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+ }
+ }
+
+ /* add list */
+
+ for (i=0; i < num_add_sids; i++) {
+ status = dcerpc_samr_AddAliasMember(b, talloc_tos(),
+ &alias_handle,
+ &add_sids[i],
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ /* del list */
+
+ for (i=0; i < num_del_sids; i++) {
+ status = dcerpc_samr_DeleteAliasMember(b, talloc_tos(),
+ &alias_handle,
+ &del_sids[i],
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (b && is_valid_policy_hnd(&alias_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupAddMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAddMembers *r)
+{
+ return NetLocalGroupModifyMembers_r(ctx, r, NULL, NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupAddMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAddMembers *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAddMembers);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupDelMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDelMembers *r)
+{
+ return NetLocalGroupModifyMembers_r(ctx, NULL, r, NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupDelMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDelMembers *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDelMembers);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupGetMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetMembers *r)
+{
+ return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupGetMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetMembers *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetMembers);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupSetMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetMembers *r)
+{
+ return NetLocalGroupModifyMembers_r(ctx, NULL, NULL, r);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupSetMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetMembers *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetMembers);
+}
diff --git a/source3/lib/netapi/netapi.c b/source3/lib/netapi/netapi.c
new file mode 100644
index 0000000..fe98216
--- /dev/null
+++ b/source3/lib/netapi/netapi.c
@@ -0,0 +1,507 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Support
+ * Copyright (C) Guenther Deschner 2007-2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "../libcli/auth/netlogon_creds_cli.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "secrets.h"
+#include "krb5_env.h"
+#include "source3/param/loadparm.h"
+#include "lib/param/param.h"
+#include "auth/gensec/gensec.h"
+
+struct libnetapi_ctx *stat_ctx = NULL;
+static bool libnetapi_initialized = false;
+
+/****************************************************************
+****************************************************************/
+
+static NET_API_STATUS libnetapi_init_private_context(struct libnetapi_ctx *ctx)
+{
+ struct libnetapi_private_ctx *priv;
+
+ if (!ctx) {
+ return W_ERROR_V(WERR_INVALID_PARAMETER);
+ }
+
+ priv = talloc_zero(ctx, struct libnetapi_private_ctx);
+ if (!priv) {
+ return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
+ }
+
+ ctx->private_data = priv;
+
+ return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+Create a libnetapi context, for use in non-Samba applications. This
+loads the smb.conf file and sets the debug level to 0, so that
+applications are not flooded with debug logs at level 10, when they
+were not expecting it.
+****************************************************************/
+
+NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
+{
+ NET_API_STATUS ret;
+ TALLOC_CTX *frame;
+ if (stat_ctx && libnetapi_initialized) {
+ *context = stat_ctx;
+ return NET_API_STATUS_SUCCESS;
+ }
+
+#if 0
+ talloc_enable_leak_report();
+#endif
+ frame = talloc_stackframe();
+
+ /* When libnetapi is invoked from an application, it does not
+ * want to be swamped with level 10 debug messages, even if
+ * this has been set for the server in smb.conf */
+ lp_set_cmdline("log level", "0");
+ setup_logging("libnetapi", DEBUG_STDERR);
+
+ if (!lp_load_global(get_dyn_CONFIGFILE())) {
+ TALLOC_FREE(frame);
+ fprintf(stderr, "error loading %s\n", get_dyn_CONFIGFILE() );
+ return W_ERROR_V(WERR_GEN_FAILURE);
+ }
+
+ load_interfaces();
+ reopen_logs();
+
+ BlockSignals(True, SIGPIPE);
+
+ ret = libnetapi_net_init(context);
+ TALLOC_FREE(frame);
+ return ret;
+}
+
+/****************************************************************
+Create a libnetapi context, for use inside the 'net' binary.
+
+As we know net has already loaded the smb.conf file, and set the debug
+level etc, this avoids doing so again (which causes trouble with -d on
+the command line).
+****************************************************************/
+
+NET_API_STATUS libnetapi_net_init(struct libnetapi_ctx **context)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct loadparm_context *lp_ctx = NULL;
+
+ ctx = talloc_zero(frame, struct libnetapi_ctx);
+ if (!ctx) {
+ TALLOC_FREE(frame);
+ return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
+ }
+
+ ctx->creds = cli_credentials_init(ctx);
+ if (ctx->creds == NULL) {
+ TALLOC_FREE(frame);
+ return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
+ }
+
+ lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
+ if (lp_ctx == NULL) {
+ TALLOC_FREE(frame);
+ return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
+ }
+
+ BlockSignals(True, SIGPIPE);
+
+ /* Ignore return code, as we might not have a smb.conf */
+ (void)cli_credentials_guess(ctx->creds, lp_ctx);
+
+ status = libnetapi_init_private_context(ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ libnetapi_initialized = true;
+
+ talloc_steal(NULL, ctx);
+ *context = stat_ctx = ctx;
+
+ TALLOC_FREE(frame);
+ return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+ Return the static libnetapi context
+****************************************************************/
+
+NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx)
+{
+ if (stat_ctx) {
+ *ctx = stat_ctx;
+ return NET_API_STATUS_SUCCESS;
+ }
+
+ return libnetapi_init(ctx);
+}
+
+/****************************************************************
+ Free the static libnetapi context
+****************************************************************/
+
+NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx)
+{
+ TALLOC_CTX *frame;
+
+ if (!ctx) {
+ return NET_API_STATUS_SUCCESS;
+ }
+
+ frame = talloc_stackframe();
+ libnetapi_samr_free(ctx);
+
+ libnetapi_shutdown_cm(ctx);
+
+ gfree_loadparm();
+ gfree_charcnv();
+ gfree_interfaces();
+
+ secrets_shutdown();
+
+ netlogon_creds_cli_close_global_db();
+
+ if (ctx == stat_ctx) {
+ stat_ctx = NULL;
+ }
+ TALLOC_FREE(ctx);
+
+ gfree_debugsyms();
+ talloc_free(frame);
+
+ return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+ Override the current log level for libnetapi
+****************************************************************/
+
+NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx,
+ const char *debuglevel)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ ctx->debuglevel = talloc_strdup(ctx, debuglevel);
+
+ if (!lp_set_cmdline("log level", debuglevel)) {
+ TALLOC_FREE(frame);
+ return W_ERROR_V(WERR_GEN_FAILURE);
+ }
+ TALLOC_FREE(frame);
+ return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_set_logfile(struct libnetapi_ctx *ctx,
+ const char *logfile)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ ctx->logfile = talloc_strdup(ctx, logfile);
+
+ if (!lp_set_cmdline("log file", logfile)) {
+ TALLOC_FREE(frame);
+ return W_ERROR_V(WERR_GEN_FAILURE);
+ }
+ debug_set_logfile(logfile);
+ setup_logging("libnetapi", DEBUG_FILE);
+ TALLOC_FREE(frame);
+ return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx,
+ char **debuglevel)
+{
+ *debuglevel = ctx->debuglevel;
+ return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+****************************************************************/
+
+/**
+ * @brief Get the username of the libnet context
+ *
+ * @param[in] ctx The netapi context
+ *
+ * @param[in] username A pointer to hold the username.
+ *
+ * @return 0 on success, an werror code otherwise.
+ */
+NET_API_STATUS libnetapi_get_username(struct libnetapi_ctx *ctx,
+ const char **username)
+{
+ if (ctx == NULL) {
+ return W_ERROR_V(WERR_INVALID_PARAMETER);
+ }
+
+ if (username != NULL) {
+ *username = cli_credentials_get_username(ctx->creds);
+ }
+
+ return NET_API_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Get the password of the libnet context
+ *
+ * @param[in] ctx The netapi context
+ *
+ * @param[in] password A pointer to hold the password.
+ *
+ * @return 0 on success, an werror code otherwise.
+ */
+NET_API_STATUS libnetapi_get_password(struct libnetapi_ctx *ctx,
+ const char **password)
+{
+ if (ctx == NULL) {
+ return W_ERROR_V(WERR_INVALID_PARAMETER);
+ }
+
+ if (password != NULL) {
+ *password = cli_credentials_get_password(ctx->creds);
+ }
+
+ return NET_API_STATUS_SUCCESS;
+}
+
+NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx,
+ const char *username)
+{
+ if (ctx == NULL || username == NULL) {
+ return W_ERROR_V(WERR_INVALID_PARAMETER);
+ }
+
+ cli_credentials_parse_string(ctx->creds, username, CRED_SPECIFIED);
+
+ return NET_API_STATUS_SUCCESS;
+}
+
+NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx,
+ const char *password)
+{
+ bool ok;
+
+ if (ctx == NULL || password == NULL) {
+ return W_ERROR_V(WERR_INVALID_PARAMETER);
+ }
+
+ ok = cli_credentials_set_password(ctx->creds, password, CRED_SPECIFIED);
+ if (!ok) {
+ return W_ERROR_V(WERR_INTERNAL_ERROR);
+ }
+
+ return NET_API_STATUS_SUCCESS;
+}
+
+NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
+ const char *workgroup)
+{
+ bool ok;
+
+ ok = cli_credentials_set_domain(ctx->creds, workgroup, CRED_SPECIFIED);
+ if (!ok) {
+ return W_ERROR_V(WERR_INTERNAL_ERROR);
+ }
+
+ return NET_API_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Set the cli_credentials to be used in the netapi context
+ *
+ * @param[in] ctx The netapi context
+ *
+ * @param[in] creds The cli_credentials which should be used by netapi.
+ *
+ * @return 0 on success, an werror code otherwise.
+ */
+NET_API_STATUS libnetapi_set_creds(struct libnetapi_ctx *ctx,
+ struct cli_credentials *creds)
+{
+ if (ctx == NULL || creds == NULL) {
+ return W_ERROR_V(WERR_INVALID_PARAMETER);
+ }
+
+ ctx->creds = creds;
+
+ return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_set_use_kerberos(struct libnetapi_ctx *ctx)
+{
+ cli_credentials_set_kerberos_state(ctx->creds,
+ CRED_USE_KERBEROS_REQUIRED,
+ CRED_SPECIFIED);
+
+ return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_get_use_kerberos(struct libnetapi_ctx *ctx,
+ int *use_kerberos)
+{
+ enum credentials_use_kerberos creds_use_kerberos;
+
+ *use_kerberos = 0;
+
+ creds_use_kerberos = cli_credentials_get_kerberos_state(ctx->creds);
+ if (creds_use_kerberos > CRED_USE_KERBEROS_DESIRED) {
+ *use_kerberos = 1;
+ }
+
+ return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_set_use_ccache(struct libnetapi_ctx *ctx)
+{
+ uint32_t gensec_features;
+
+ gensec_features = cli_credentials_get_gensec_features(ctx->creds);
+ gensec_features |= GENSEC_FEATURE_NTLM_CCACHE;
+ cli_credentials_set_gensec_features(ctx->creds,
+ gensec_features,
+ CRED_SPECIFIED);
+
+ return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+Return a libnetapi error as a string, caller must free with NetApiBufferFree
+****************************************************************/
+
+char *libnetapi_errstr(NET_API_STATUS status)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ char *ret;
+ if (status & 0xc0000000) {
+ ret = talloc_strdup(NULL,
+ get_friendly_nt_error_msg(NT_STATUS(status)));
+ } else {
+ ret = talloc_strdup(NULL,
+ get_friendly_werror_msg(W_ERROR(status)));
+ }
+ TALLOC_FREE(frame);
+ return ret;
+}
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx,
+ const char *format, ...)
+{
+ va_list args;
+
+ TALLOC_FREE(ctx->error_string);
+
+ va_start(args, format);
+ ctx->error_string = talloc_vasprintf(ctx, format, args);
+ va_end(args);
+
+ if (!ctx->error_string) {
+ return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
+ }
+ return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+Return a libnetapi_errstr(), caller must free with NetApiBufferFree
+****************************************************************/
+
+char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
+ NET_API_STATUS status_in)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *tmp_ctx = ctx;
+
+ if (!tmp_ctx) {
+ status = libnetapi_getctx(&tmp_ctx);
+ if (status != 0) {
+ return NULL;
+ }
+ }
+
+ if (tmp_ctx->error_string) {
+ return talloc_strdup(NULL, tmp_ctx->error_string);
+ }
+
+ return libnetapi_errstr(status_in);
+}
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS NetApiBufferAllocate(uint32_t byte_count,
+ void **buffer)
+{
+ void *buf = NULL;
+
+ if (!buffer) {
+ return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
+ }
+
+ if (byte_count == 0) {
+ goto done;
+ }
+
+ buf = talloc_size(NULL, byte_count);
+ if (!buf) {
+ return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
+ }
+
+ done:
+ *buffer = buf;
+
+ return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS NetApiBufferFree(void *buffer)
+{
+ if (!buffer) {
+ return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
+ }
+
+ talloc_free(buffer);
+
+ return NET_API_STATUS_SUCCESS;
+}
diff --git a/source3/lib/netapi/netapi.h b/source3/lib/netapi/netapi.h
new file mode 100644
index 0000000..df465ae
--- /dev/null
+++ b/source3/lib/netapi/netapi.h
@@ -0,0 +1,2735 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Support
+ * Copyright (C) Guenther Deschner 2007-2009
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LIB_NETAPI_H__
+#define __LIB_NETAPI_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct cli_credentials;
+
+/****************************************************************
+ NET_API_STATUS
+****************************************************************/
+typedef enum {
+ NET_API_STATUS_SUCCESS = 0
+} NET_API_STATUS;
+
+#define ERROR_MORE_DATA ( 234L )
+
+#define ENCRYPTED_PWLEN ( 16 )
+
+/****************************************************************
+****************************************************************/
+
+#ifndef _HEADER_misc
+
+struct GUID {
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_hi_and_version;
+ uint8_t clock_seq[2];
+ uint8_t node[6];
+};
+
+#endif /* _HEADER_misc */
+
+#ifndef _HEADER_libnetapi
+
+#ifndef MAXSUBAUTHS
+#define MAXSUBAUTHS 15 /* max sub authorities in a SID */
+#endif
+
+struct domsid {
+ uint8_t sid_rev_num;
+ uint8_t num_auths;
+ uint8_t id_auth[6];
+ uint32_t sub_auths[MAXSUBAUTHS];
+};
+
+struct DOMAIN_CONTROLLER_INFO {
+ const char * domain_controller_name;
+ const char * domain_controller_address;
+ uint32_t domain_controller_address_type;
+ struct GUID domain_guid;
+ const char * domain_name;
+ const char * dns_forest_name;
+ uint32_t flags;
+ const char * dc_site_name;
+ const char * client_site_name;
+};
+
+/* bitmap NetJoinFlags */
+#define NETSETUP_JOIN_DOMAIN ( 0x00000001 )
+#define NETSETUP_ACCT_CREATE ( 0x00000002 )
+#define NETSETUP_ACCT_DELETE ( 0x00000004 )
+#define NETSETUP_WIN9X_UPGRADE ( 0x00000010 )
+#define NETSETUP_DOMAIN_JOIN_IF_JOINED ( 0x00000020 )
+#define NETSETUP_JOIN_UNSECURE ( 0x00000040 )
+#define NETSETUP_MACHINE_PWD_PASSED ( 0x00000080 )
+#define NETSETUP_DEFER_SPN_SET ( 0x00000100 )
+#define NETSETUP_JOIN_DC_ACCOUNT ( 0x00000200 )
+#define NETSETUP_JOIN_WITH_NEW_NAME ( 0x00000400 )
+#define NETSETUP_JOIN_READONLY ( 0x00000800 )
+#define NETSETUP_AMBIGUOUS_DC ( 0x00001000 )
+#define NETSETUP_NO_NETLOGON_CACHE ( 0x00002000 )
+#define NETSETUP_DONT_CONTROL_SERVICES ( 0x00004000 )
+#define NETSETUP_SET_MACHINE_NAME ( 0x00008000 )
+#define NETSETUP_FORCE_SPN_SET ( 0x00010000 )
+#define NETSETUP_NO_ACCT_REUSE ( 0x00020000 )
+#define NETSETUP_INSTALL_INVOCATION ( 0x00040000 )
+#define NETSETUP_IGNORE_UNSUPPORTED_FLAGS ( 0x10000000 )
+
+/* bitmap NetProvisionFlags */
+#define NETSETUP_PROVISION_DOWNLEVEL_PRIV_SUPPORT ( 0x00000001 )
+#define NETSETUP_PROVISION_REUSE_ACCOUNT ( 0x00000002 )
+#define NETSETUP_PROVISION_USE_DEFAULT_PASSWORD ( 0x00000004 )
+#define NETSETUP_PROVISION_SKIP_ACCOUNT_SEARCH ( 0x00000008 )
+#define NETSETUP_PROVISION_ROOT_CA_CERTS ( 0x00000010 )
+
+/* bitmap NetProvisionJoinFlags */
+#define NETSETUP_PROVISION_ONLINE_CALLER ( 0x40000000 )
+
+#define FILTER_TEMP_DUPLICATE_ACCOUNT ( 0x0001 )
+#define FILTER_NORMAL_ACCOUNT ( 0x0002 )
+#define FILTER_INTERDOMAIN_TRUST_ACCOUNT ( 0x0008 )
+#define FILTER_WORKSTATION_TRUST_ACCOUNT ( 0x0010 )
+#define FILTER_SERVER_TRUST_ACCOUNT ( 0x0020 )
+
+#define TIMEQ_FOREVER ( (uint32_t)-1L )
+
+enum NETSETUP_JOIN_STATUS {
+ NetSetupUnknownStatus=0,
+ NetSetupUnjoined=1,
+ NetSetupWorkgroupName=2,
+ NetSetupDomainName=3
+};
+
+struct SERVER_INFO_100 {
+ uint32_t sv100_platform_id;
+ const char * sv100_name;
+};
+
+struct SERVER_INFO_101 {
+ uint32_t sv101_platform_id;
+ const char * sv101_name;
+ uint32_t sv101_version_major;
+ uint32_t sv101_version_minor;
+ uint32_t sv101_type;
+ const char * sv101_comment;
+};
+
+struct SERVER_INFO_102 {
+ uint32_t sv102_platform_id;
+ const char * sv102_name;
+ uint32_t sv102_version_major;
+ uint32_t sv102_version_minor;
+ uint32_t sv102_type;
+ const char * sv102_comment;
+ uint32_t sv102_users;
+ uint32_t sv102_disc;
+ uint8_t sv102_hidden;
+ uint32_t sv102_announce;
+ uint32_t sv102_anndelta;
+ uint32_t sv102_licenses;
+ const char * sv102_userpath;
+};
+
+struct SERVER_INFO_402 {
+ uint32_t sv402_ulist_mtime;
+ uint32_t sv402_glist_mtime;
+ uint32_t sv402_alist_mtime;
+ const char * sv402_alerts;
+ uint32_t sv402_security;
+ uint32_t sv402_numadmin;
+ uint32_t sv402_lanmask;
+ const char * sv402_guestacct;
+ uint32_t sv402_chdevs;
+ uint32_t sv402_chdevq;
+ uint32_t sv402_chdevjobs;
+ uint32_t sv402_connections;
+ uint32_t sv402_shares;
+ uint32_t sv402_openfiles;
+ uint32_t sv402_sessopens;
+ uint32_t sv402_sessvcs;
+ uint32_t sv402_sessreqs;
+ uint32_t sv402_opensearch;
+ uint32_t sv402_activelocks;
+ uint32_t sv402_numreqbuf;
+ uint32_t sv402_sizreqbuf;
+ uint32_t sv402_numbigbuf;
+ uint32_t sv402_numfiletasks;
+ uint32_t sv402_alertsched;
+ uint32_t sv402_erroralert;
+ uint32_t sv402_logonalert;
+ uint32_t sv402_accessalert;
+ uint32_t sv402_diskalert;
+ uint32_t sv402_netioalert;
+ uint32_t sv402_maxauditsz;
+ const char * sv402_srvheuristics;
+};
+
+struct SERVER_INFO_403 {
+ uint32_t sv403_ulist_mtime;
+ uint32_t sv403_glist_mtime;
+ uint32_t sv403_alist_mtime;
+ const char * sv403_alerts;
+ uint32_t sv403_security;
+ uint32_t sv403_numadmin;
+ uint32_t sv403_lanmask;
+ const char * sv403_guestacct;
+ uint32_t sv403_chdevs;
+ uint32_t sv403_chdevq;
+ uint32_t sv403_chdevjobs;
+ uint32_t sv403_connections;
+ uint32_t sv403_shares;
+ uint32_t sv403_openfiles;
+ uint32_t sv403_sessopens;
+ uint32_t sv403_sessvcs;
+ uint32_t sv403_sessreqs;
+ uint32_t sv403_opensearch;
+ uint32_t sv403_activelocks;
+ uint32_t sv403_numreqbuf;
+ uint32_t sv403_sizreqbuf;
+ uint32_t sv403_numbigbuf;
+ uint32_t sv403_numfiletasks;
+ uint32_t sv403_alertsched;
+ uint32_t sv403_erroralert;
+ uint32_t sv403_logonalert;
+ uint32_t sv403_accessalert;
+ uint32_t sv403_diskalert;
+ uint32_t sv403_netioalert;
+ uint32_t sv403_maxauditsz;
+ const char * sv403_srvheuristics;
+ uint32_t sv403_auditedevents;
+ uint32_t sv403_autoprofile;
+ const char * sv403_autopath;
+};
+
+struct SERVER_INFO_502 {
+ uint32_t sv502_sessopens;
+ uint32_t sv502_sessvcs;
+ uint32_t sv502_opensearch;
+ uint32_t sv502_sizreqbuf;
+ uint32_t sv502_initworkitems;
+ uint32_t sv502_maxworkitems;
+ uint32_t sv502_rawworkitems;
+ uint32_t sv502_irpstacksize;
+ uint32_t sv502_maxrawbuflen;
+ uint32_t sv502_sessusers;
+ uint32_t sv502_sessconns;
+ uint32_t sv502_maxpagedmemoryusage;
+ uint32_t sv502_maxnonpagedmemoryusage;
+ uint8_t sv502_enablesoftcompat;
+ uint8_t sv502_enableforcedlogoff;
+ uint8_t sv502_timesource;
+ uint8_t sv502_acceptdownlevelapis;
+ uint8_t sv502_lmannounce;
+};
+
+struct SERVER_INFO_503 {
+ uint32_t sv503_sessopens;
+ uint32_t sv503_sessvcs;
+ uint32_t sv503_opensearch;
+ uint32_t sv503_sizreqbuf;
+ uint32_t sv503_initworkitems;
+ uint32_t sv503_maxworkitems;
+ uint32_t sv503_rawworkitems;
+ uint32_t sv503_irpstacksize;
+ uint32_t sv503_maxrawbuflen;
+ uint32_t sv503_sessusers;
+ uint32_t sv503_sessconns;
+ uint32_t sv503_maxpagedmemoryusage;
+ uint32_t sv503_maxnonpagedmemoryusage;
+ uint8_t sv503_enablesoftcompat;
+ uint8_t sv503_enableforcedlogoff;
+ uint8_t sv503_timesource;
+ uint8_t sv503_acceptdownlevelapis;
+ uint8_t sv503_lmannounce;
+ const char * sv503_domain;
+ uint32_t sv503_maxcopyreadlen;
+ uint32_t sv503_maxcopywritelen;
+ uint32_t sv503_minkeepsearch;
+ uint32_t sv503_maxkeepsearch;
+ uint32_t sv503_minkeepcomplsearch;
+ uint32_t sv503_maxkeepcomplsearch;
+ uint32_t sv503_threadcountadd;
+ uint32_t sv503_numblockthreads;
+ uint32_t sv503_scavtimeout;
+ uint32_t sv503_minrcvqueue;
+ uint32_t sv503_minfreeworkitems;
+ uint32_t sv503_xactmemsize;
+ uint32_t sv503_threadpriority;
+ uint32_t sv503_maxmpxct;
+ uint32_t sv503_oplockbreakwait;
+ uint32_t sv503_oplockbreakresponsewait;
+ uint8_t sv503_enableoplocks;
+ uint8_t sv503_enableoplockforceclose;
+ uint8_t sv503_enablefcbopens;
+ uint8_t sv503_enableraw;
+ uint8_t sv503_enablesharednetdrives;
+ uint32_t sv503_minfreeconnections;
+ uint32_t sv503_maxfreeconnections;
+};
+
+struct SERVER_INFO_599 {
+ uint32_t sv599_sessopens;
+ uint32_t sv599_sessvcs;
+ uint32_t sv599_opensearch;
+ uint32_t sv599_sizreqbuf;
+ uint32_t sv599_initworkitems;
+ uint32_t sv599_maxworkitems;
+ uint32_t sv599_rawworkitems;
+ uint32_t sv599_irpstacksize;
+ uint32_t sv599_maxrawbuflen;
+ uint32_t sv599_sessusers;
+ uint32_t sv599_sessconns;
+ uint32_t sv599_maxpagedmemoryusage;
+ uint32_t sv599_maxnonpagedmemoryusage;
+ uint8_t sv599_enablesoftcompat;
+ uint8_t sv599_enableforcedlogoff;
+ uint8_t sv599_timesource;
+ uint8_t sv599_acceptdownlevelapis;
+ uint8_t sv599_lmannounce;
+ const char * sv599_domain;
+ uint32_t sv599_maxcopyreadlen;
+ uint32_t sv599_maxcopywritelen;
+ uint32_t sv599_minkeepsearch;
+ uint32_t sv599_maxkeepsearch;
+ uint32_t sv599_minkeepcomplsearch;
+ uint32_t sv599_maxkeepcomplsearch;
+ uint32_t sv599_threadcountadd;
+ uint32_t sv599_numblockthreads;
+ uint32_t sv599_scavtimeout;
+ uint32_t sv599_minrcvqueue;
+ uint32_t sv599_minfreeworkitems;
+ uint32_t sv599_xactmemsize;
+ uint32_t sv599_threadpriority;
+ uint32_t sv599_maxmpxct;
+ uint32_t sv599_oplockbreakwait;
+ uint32_t sv599_oplockbreakresponsewait;
+ uint8_t sv599_enableoplocks;
+ uint8_t sv599_enableoplockforceclose;
+ uint8_t sv599_enablefcbopens;
+ uint8_t sv599_enableraw;
+ uint8_t sv599_enablesharednetdrives;
+ uint32_t sv599_minfreeconnections;
+ uint32_t sv599_maxfreeconnections;
+ uint32_t sv599_initsesstable;
+ uint32_t sv599_initconntable;
+ uint32_t sv599_initfiletable;
+ uint32_t sv599_initsearchtable;
+ uint32_t sv599_alertschedule;
+ uint32_t sv599_errorthreshold;
+ uint32_t sv599_networkerrorthreshold;
+ uint32_t sv599_diskspacethreshold;
+ uint32_t sv599_reserved;
+ uint32_t sv599_maxlinkdelay;
+ uint32_t sv599_minlinkthroughput;
+ uint32_t sv599_linkinfovalidtime;
+ uint32_t sv599_scavqosinfoupdatetime;
+ uint32_t sv599_maxworkitemidletime;
+};
+
+struct SERVER_INFO_598 {
+ uint32_t sv598_maxrawworkitems;
+ uint32_t sv598_maxthreadsperqueue;
+ uint32_t sv598_producttype;
+ uint32_t sv598_serversize;
+ uint32_t sv598_connectionlessautodisc;
+ uint32_t sv598_sharingviolationretries;
+ uint32_t sv598_sharingviolationdelay;
+ uint32_t sv598_maxglobalopensearch;
+ uint32_t sv598_removeduplicatesearches;
+ uint32_t sv598_lockviolationoffset;
+ uint32_t sv598_lockviolationdelay;
+ uint32_t sv598_mdlreadswitchover;
+ uint32_t sv598_cachedopenlimit;
+ uint32_t sv598_otherqueueaffinity;
+ uint8_t sv598_restrictnullsessaccess;
+ uint8_t sv598_enablewfw311directipx;
+ uint32_t sv598_queuesamplesecs;
+ uint32_t sv598_balancecount;
+ uint32_t sv598_preferredaffinity;
+ uint32_t sv598_maxfreerfcbs;
+ uint32_t sv598_maxfreemfcbs;
+ uint32_t sv598_maxfreelfcbs;
+ uint32_t sv598_maxfreepagedpoolchunks;
+ uint32_t sv598_minpagedpoolchunksize;
+ uint32_t sv598_maxpagedpoolchunksize;
+ uint8_t sv598_sendsfrompreferredprocessor;
+ uint32_t sv598_cacheddirectorylimit;
+ uint32_t sv598_maxcopylength;
+ uint8_t sv598_enablecompression;
+ uint8_t sv598_autosharewks;
+ uint8_t sv598_autoshareserver;
+ uint8_t sv598_enablesecuritysignature;
+ uint8_t sv598_requiresecuritysignature;
+ uint32_t sv598_minclientbuffersize;
+ struct GUID sv598_serverguid;
+ uint32_t sv598_ConnectionNoSessionsTimeout;
+ uint32_t sv598_IdleThreadTimeOut;
+ uint8_t sv598_enableW9xsecuritysignature;
+ uint8_t sv598_enforcekerberosreauthentication;
+ uint8_t sv598_disabledos;
+ uint32_t sv598_lowdiskspaceminimum;
+ uint8_t sv598_disablestrictnamechecking;
+};
+
+struct SERVER_INFO_1005 {
+ const char * sv1005_comment;
+};
+
+struct SERVER_INFO_1107 {
+ uint32_t sv1107_users;
+};
+
+struct SERVER_INFO_1010 {
+ int32_t sv1010_disc;
+};
+
+struct SERVER_INFO_1016 {
+ uint8_t sv1016_hidden;
+};
+
+struct SERVER_INFO_1017 {
+ uint32_t sv1017_announce;
+};
+
+struct SERVER_INFO_1018 {
+ uint32_t sv1018_anndelta;
+};
+
+struct SERVER_INFO_1501 {
+ uint32_t sv1501_sessopens;
+};
+
+struct SERVER_INFO_1502 {
+ uint32_t sv1502_sessvcs;
+};
+
+struct SERVER_INFO_1503 {
+ uint32_t sv1503_opensearch;
+};
+
+struct SERVER_INFO_1506 {
+ uint32_t sv1506_maxworkitems;
+};
+
+struct SERVER_INFO_1509 {
+ uint32_t sv1509_maxrawbuflen;
+};
+
+struct SERVER_INFO_1510 {
+ uint32_t sv1510_sessusers;
+};
+
+struct SERVER_INFO_1511 {
+ uint32_t sv1511_sessconns;
+};
+
+struct SERVER_INFO_1512 {
+ uint32_t sv1512_maxnonpagedmemoryusage;
+};
+
+struct SERVER_INFO_1513 {
+ uint32_t sv1513_maxpagedmemoryusage;
+};
+
+struct SERVER_INFO_1514 {
+ uint8_t sv1514_enablesoftcompat;
+};
+
+struct SERVER_INFO_1515 {
+ uint8_t sv1515_enableforcedlogoff;
+};
+
+struct SERVER_INFO_1516 {
+ uint8_t sv1516_timesource;
+};
+
+struct SERVER_INFO_1518 {
+ uint8_t sv1518_lmannounce;
+};
+
+struct SERVER_INFO_1520 {
+ uint32_t sv1520_maxcopyreadlen;
+};
+
+struct SERVER_INFO_1521 {
+ uint32_t sv1521_maxcopywritelen;
+};
+
+struct SERVER_INFO_1522 {
+ uint32_t sv1522_minkeepsearch;
+};
+
+struct SERVER_INFO_1523 {
+ uint32_t sv1523_maxkeepsearch;
+};
+
+struct SERVER_INFO_1524 {
+ uint32_t sv1524_minkeepcomplsearch;
+};
+
+struct SERVER_INFO_1525 {
+ uint32_t sv1525_maxkeepcomplsearch;
+};
+
+struct SERVER_INFO_1528 {
+ uint32_t sv1528_scavtimeout;
+};
+
+struct SERVER_INFO_1529 {
+ uint32_t sv1529_minrcvqueue;
+};
+
+struct SERVER_INFO_1530 {
+ uint32_t sv1530_minfreeworkitems;
+};
+
+struct SERVER_INFO_1533 {
+ uint32_t sv1533_maxmpxct;
+};
+
+struct SERVER_INFO_1534 {
+ uint32_t sv1534_oplockbreakwait;
+};
+
+struct SERVER_INFO_1535 {
+ uint32_t sv1535_oplockbreakresponsewait;
+};
+
+struct SERVER_INFO_1536 {
+ uint8_t sv1536_enableoplocks;
+};
+
+struct SERVER_INFO_1537 {
+ uint8_t sv1537_enableoplockforceclose;
+};
+
+struct SERVER_INFO_1538 {
+ uint8_t sv1538_enablefcbopens;
+};
+
+struct SERVER_INFO_1539 {
+ uint8_t sv1539_enableraw;
+};
+
+struct SERVER_INFO_1540 {
+ uint8_t sv1540_enablesharednetdrives;
+};
+
+struct SERVER_INFO_1541 {
+ uint8_t sv1541_minfreeconnections;
+};
+
+struct SERVER_INFO_1542 {
+ uint8_t sv1542_maxfreeconnections;
+};
+
+struct SERVER_INFO_1543 {
+ uint32_t sv1543_initsesstable;
+};
+
+struct SERVER_INFO_1544 {
+ uint32_t sv1544_initconntable;
+};
+
+struct SERVER_INFO_1545 {
+ uint32_t sv1545_initfiletable;
+};
+
+struct SERVER_INFO_1546 {
+ uint32_t sv1546_initsearchtable;
+};
+
+struct SERVER_INFO_1547 {
+ uint32_t sv1547_alertschedule;
+};
+
+struct SERVER_INFO_1548 {
+ uint32_t sv1548_errorthreshold;
+};
+
+struct SERVER_INFO_1549 {
+ uint32_t sv1549_networkerrorthreshold;
+};
+
+struct SERVER_INFO_1550 {
+ uint32_t sv1550_diskspacethreshold;
+};
+
+struct SERVER_INFO_1552 {
+ uint32_t sv1552_maxlinkdelay;
+};
+
+struct SERVER_INFO_1553 {
+ uint32_t sv1553_minlinkthroughput;
+};
+
+struct SERVER_INFO_1554 {
+ uint32_t sv1554_linkinfovalidtime;
+};
+
+struct SERVER_INFO_1555 {
+ uint32_t sv1555_scavqosinfoupdatetime;
+};
+
+struct SERVER_INFO_1556 {
+ uint32_t sv1556_maxworkitemidletime;
+};
+
+struct SERVER_INFO_1557 {
+ uint32_t sv1557_maxrawworkitems;
+};
+
+struct SERVER_INFO_1560 {
+ uint32_t sv1560_producttype;
+};
+
+struct SERVER_INFO_1561 {
+ uint32_t sv1561_serversize;
+};
+
+struct SERVER_INFO_1562 {
+ uint32_t sv1562_connectionlessautodisc;
+};
+
+struct SERVER_INFO_1563 {
+ uint32_t sv1563_sharingviolationretries;
+};
+
+struct SERVER_INFO_1564 {
+ uint32_t sv1564_sharingviolationdelay;
+};
+
+struct SERVER_INFO_1565 {
+ uint32_t sv1565_maxglobalopensearch;
+};
+
+struct SERVER_INFO_1566 {
+ uint8_t sv1566_removeduplicatesearches;
+};
+
+struct SERVER_INFO_1567 {
+ uint32_t sv1567_lockviolationretries;
+};
+
+struct SERVER_INFO_1568 {
+ uint32_t sv1568_lockviolationoffset;
+};
+
+struct SERVER_INFO_1569 {
+ uint32_t sv1569_lockviolationdelay;
+};
+
+struct SERVER_INFO_1570 {
+ uint32_t sv1570_mdlreadswitchover;
+};
+
+struct SERVER_INFO_1571 {
+ uint32_t sv1571_cachedopenlimit;
+};
+
+struct SERVER_INFO_1572 {
+ uint32_t sv1572_criticalthreads;
+};
+
+struct SERVER_INFO_1573 {
+ uint32_t sv1573_restrictnullsessaccess;
+};
+
+struct SERVER_INFO_1574 {
+ uint32_t sv1574_enablewfw311directipx;
+};
+
+struct SERVER_INFO_1575 {
+ uint32_t sv1575_otherqueueaffinity;
+};
+
+struct SERVER_INFO_1576 {
+ uint32_t sv1576_queuesamplesecs;
+};
+
+struct SERVER_INFO_1577 {
+ uint32_t sv1577_balancecount;
+};
+
+struct SERVER_INFO_1578 {
+ uint32_t sv1578_preferredaffinity;
+};
+
+struct SERVER_INFO_1579 {
+ uint32_t sv1579_maxfreerfcbs;
+};
+
+struct SERVER_INFO_1580 {
+ uint32_t sv1580_maxfreemfcbs;
+};
+
+struct SERVER_INFO_1581 {
+ uint32_t sv1581_maxfreemlcbs;
+};
+
+struct SERVER_INFO_1582 {
+ uint32_t sv1582_maxfreepagedpoolchunks;
+};
+
+struct SERVER_INFO_1583 {
+ uint32_t sv1583_minpagedpoolchunksize;
+};
+
+struct SERVER_INFO_1584 {
+ uint32_t sv1584_maxpagedpoolchunksize;
+};
+
+struct SERVER_INFO_1585 {
+ uint8_t sv1585_sendsfrompreferredprocessor;
+};
+
+struct SERVER_INFO_1586 {
+ uint32_t sv1586_maxthreadsperqueue;
+};
+
+struct SERVER_INFO_1587 {
+ uint32_t sv1587_cacheddirectorylimit;
+};
+
+struct SERVER_INFO_1588 {
+ uint32_t sv1588_maxcopylength;
+};
+
+struct SERVER_INFO_1590 {
+ uint32_t sv1590_enablecompression;
+};
+
+struct SERVER_INFO_1591 {
+ uint32_t sv1591_autosharewks;
+};
+
+struct SERVER_INFO_1592 {
+ uint32_t sv1592_autosharewks;
+};
+
+struct SERVER_INFO_1593 {
+ uint32_t sv1593_enablesecuritysignature;
+};
+
+struct SERVER_INFO_1594 {
+ uint32_t sv1594_requiresecuritysignature;
+};
+
+struct SERVER_INFO_1595 {
+ uint32_t sv1595_minclientbuffersize;
+};
+
+struct SERVER_INFO_1596 {
+ uint32_t sv1596_ConnectionNoSessionsTimeout;
+};
+
+struct SERVER_INFO_1597 {
+ uint32_t sv1597_IdleThreadTimeOut;
+};
+
+struct SERVER_INFO_1598 {
+ uint32_t sv1598_enableW9xsecuritysignature;
+};
+
+struct SERVER_INFO_1599 {
+ uint8_t sv1598_enforcekerberosreauthentication;
+};
+
+struct SERVER_INFO_1600 {
+ uint8_t sv1598_disabledos;
+};
+
+struct SERVER_INFO_1601 {
+ uint32_t sv1598_lowdiskspaceminimum;
+};
+
+struct SERVER_INFO_1602 {
+ uint8_t sv_1598_disablestrictnamechecking;
+};
+
+struct USER_INFO_0 {
+ const char * usri0_name;
+};
+
+#define USER_PRIV_GUEST ( 0 )
+#define USER_PRIV_USER ( 1 )
+#define USER_PRIV_ADMIN ( 2 )
+
+struct USER_INFO_1 {
+ const char * usri1_name;
+ const char * usri1_password;
+ uint32_t usri1_password_age;
+ uint32_t usri1_priv;
+ const char * usri1_home_dir;
+ const char * usri1_comment;
+ uint32_t usri1_flags;
+ const char * usri1_script_path;
+};
+
+#define AF_OP_PRINT ( 0x1 )
+#define AF_OP_COMM ( 0x2 )
+#define AF_OP_SERVER ( 0x4 )
+#define AF_OP_ACCOUNTS ( 0x8 )
+
+struct USER_INFO_2 {
+ const char * usri2_name;
+ const char * usri2_password;
+ uint32_t usri2_password_age;
+ uint32_t usri2_priv;
+ const char * usri2_home_dir;
+ const char * usri2_comment;
+ uint32_t usri2_flags;
+ const char * usri2_script_path;
+ uint32_t usri2_auth_flags;
+ const char * usri2_full_name;
+ const char * usri2_usr_comment;
+ const char * usri2_parms;
+ const char * usri2_workstations;
+ uint32_t usri2_last_logon;
+ uint32_t usri2_last_logoff;
+ uint32_t usri2_acct_expires;
+ uint32_t usri2_max_storage;
+ uint32_t usri2_units_per_week;
+ uint8_t *usri2_logon_hours;/* [unique] */
+ uint32_t usri2_bad_pw_count;
+ uint32_t usri2_num_logons;
+ const char * usri2_logon_server;
+ uint32_t usri2_country_code;
+ uint32_t usri2_code_page;
+};
+
+struct USER_INFO_3 {
+ const char * usri3_name;
+ uint32_t usri3_password_age;
+ uint32_t usri3_priv;
+ const char * usri3_home_dir;
+ const char * usri3_comment;
+ uint32_t usri3_flags;
+ const char * usri3_script_path;
+ uint32_t usri3_auth_flags;
+ const char * usri3_full_name;
+ const char * usri3_usr_comment;
+ const char * usri3_parms;
+ const char * usri3_workstations;
+ uint32_t usri3_last_logon;
+ uint32_t usri3_last_logoff;
+ uint32_t usri3_acct_expires;
+ uint32_t usri3_max_storage;
+ uint32_t usri3_units_per_week;
+ uint8_t *usri3_logon_hours;/* [unique] */
+ uint32_t usri3_bad_pw_count;
+ uint32_t usri3_num_logons;
+ const char * usri3_logon_server;
+ uint32_t usri3_country_code;
+ uint32_t usri3_code_page;
+ uint32_t usri3_user_id;
+ uint32_t usri3_primary_group_id;
+ const char * usri3_profile;
+ const char * usri3_home_dir_drive;
+ uint32_t usri3_password_expired;
+};
+
+struct USER_INFO_4 {
+ const char * usri4_name;
+ const char * usri4_password;
+ uint32_t usri4_password_age;
+ uint32_t usri4_priv;
+ const char * usri4_home_dir;
+ const char * usri4_comment;
+ uint32_t usri4_flags;
+ const char * usri4_script_path;
+ uint32_t usri4_auth_flags;
+ const char * usri4_full_name;
+ const char * usri4_usr_comment;
+ const char * usri4_parms;
+ const char * usri4_workstations;
+ uint32_t usri4_last_logon;
+ uint32_t usri4_last_logoff;
+ uint32_t usri4_acct_expires;
+ uint32_t usri4_max_storage;
+ uint32_t usri4_units_per_week;
+ uint8_t *usri4_logon_hours;/* [unique] */
+ uint32_t usri4_bad_pw_count;
+ uint32_t usri4_num_logons;
+ const char * usri4_logon_server;
+ uint32_t usri4_country_code;
+ uint32_t usri4_code_page;
+ struct domsid *usri4_user_sid;/* [unique] */
+ uint32_t usri4_primary_group_id;
+ const char * usri4_profile;
+ const char * usri4_home_dir_drive;
+ uint32_t usri4_password_expired;
+};
+
+struct USER_INFO_10 {
+ const char * usri10_name;
+ const char * usri10_comment;
+ const char * usri10_usr_comment;
+ const char * usri10_full_name;
+};
+
+struct USER_INFO_11 {
+ const char * usri11_name;
+ const char * usri11_comment;
+ const char * usri11_usr_comment;
+ const char * usri11_full_name;
+ uint32_t usri11_priv;
+ uint32_t usri11_auth_flags;
+ uint32_t usri11_password_age;
+ const char * usri11_home_dir;
+ const char * usri11_parms;
+ uint32_t usri11_last_logon;
+ uint32_t usri11_last_logoff;
+ uint32_t usri11_bad_pw_count;
+ uint32_t usri11_num_logons;
+ const char * usri11_logon_server;
+ uint32_t usri11_country_code;
+ const char * usri11_workstations;
+ uint32_t usri11_max_storage;
+ uint32_t usri11_units_per_week;
+ uint8_t *usri11_logon_hours;/* [unique] */
+ uint32_t usri11_code_page;
+};
+
+struct USER_INFO_20 {
+ const char * usri20_name;
+ const char * usri20_full_name;
+ const char * usri20_comment;
+ uint32_t usri20_flags;
+ uint32_t usri20_user_id;
+};
+
+struct USER_INFO_21 {
+ uint8_t *usri21_password;
+};
+
+struct USER_INFO_22 {
+ const char * usri22_name;
+ uint8_t *usri22_password;
+ uint32_t usri22_password_age;
+ uint32_t usri22_priv;
+ const char * usri22_home_dir;
+ const char * usri22_comment;
+ uint32_t usri22_flags;
+ uint32_t usri22_script_path;
+ uint32_t usri22_auth_flags;
+ const char * usri22_full_name;
+ const char * usri22_usr_comment;
+ const char * usri22_parms;
+ const char * usri22_workstations;
+ uint32_t usri22_last_logon;
+ uint32_t usri22_last_logoff;
+ uint32_t usri22_acct_expires;
+ uint32_t usri22_max_storage;
+ uint32_t usri22_units_per_week;
+ uint8_t *usri22_logon_hours;/* [unique] */
+ uint32_t usri22_bad_pw_count;
+ uint32_t usri22_num_logons;
+ const char * usri22_logon_server;
+ uint32_t usri22_country_code;
+ uint32_t usri22_code_page;
+};
+
+struct USER_INFO_23 {
+ const char * usri23_name;
+ const char * usri23_full_name;
+ const char * usri23_comment;
+ uint32_t usri23_flags;
+ struct domsid *usri23_user_sid;/* [unique] */
+};
+
+struct USER_INFO_1003 {
+ const char * usri1003_password;
+};
+
+struct USER_INFO_1005 {
+ uint32_t usri1005_priv;
+};
+
+struct USER_INFO_1006 {
+ const char * usri1006_home_dir;
+};
+
+struct USER_INFO_1007 {
+ const char * usri1007_comment;
+};
+
+struct USER_INFO_1008 {
+ uint32_t usri1008_flags;
+};
+
+struct USER_INFO_1009 {
+ const char * usri1009_script_path;
+};
+
+struct USER_INFO_1010 {
+ uint32_t usri1010_auth_flags;
+};
+
+struct USER_INFO_1011 {
+ const char * usri1011_full_name;
+};
+
+struct USER_INFO_1012 {
+ const char * usri1012_usr_comment;
+};
+
+struct USER_INFO_1013 {
+ const char * usri1013_parms;
+};
+
+struct USER_INFO_1014 {
+ const char * usri1014_workstations;
+};
+
+struct USER_INFO_1017 {
+ uint32_t usri1017_acct_expires;
+};
+
+struct USER_INFO_1018 {
+ uint32_t usri1018_max_storage;
+};
+
+struct USER_INFO_1020 {
+ uint32_t usri1020_units_per_week;
+ uint8_t *usri1020_logon_hours;/* [unique] */
+};
+
+struct USER_INFO_1023 {
+ const char * usri1023_logon_server;
+};
+
+struct USER_INFO_1024 {
+ uint32_t usri1024_country_code;
+};
+
+struct USER_INFO_1025 {
+ uint32_t usri1025_code_page;
+};
+
+struct USER_INFO_1051 {
+ uint32_t usri1051_primary_group_id;
+};
+
+struct USER_INFO_1052 {
+ const char * usri1052_profile;
+};
+
+struct USER_INFO_1053 {
+ const char * usri1053_home_dir_drive;
+};
+
+struct USER_MODALS_INFO_0 {
+ uint32_t usrmod0_min_passwd_len;
+ uint32_t usrmod0_max_passwd_age;
+ uint32_t usrmod0_min_passwd_age;
+ uint32_t usrmod0_force_logoff;
+ uint32_t usrmod0_password_hist_len;
+};
+
+struct USER_MODALS_INFO_1 {
+ uint32_t usrmod1_role;
+ const char * usrmod1_primary;
+};
+
+struct USER_MODALS_INFO_2 {
+ const char * usrmod2_domain_name;
+ struct domsid *usrmod2_domain_id;/* [unique] */
+};
+
+struct USER_MODALS_INFO_3 {
+ uint32_t usrmod3_lockout_duration;
+ uint32_t usrmod3_lockout_observation_window;
+ uint32_t usrmod3_lockout_threshold;
+};
+
+struct USER_MODALS_INFO_1001 {
+ uint32_t usrmod1001_min_passwd_len;
+};
+
+struct USER_MODALS_INFO_1002 {
+ uint32_t usrmod1002_max_passwd_age;
+};
+
+struct USER_MODALS_INFO_1003 {
+ uint32_t usrmod1003_min_passwd_age;
+};
+
+struct USER_MODALS_INFO_1004 {
+ uint32_t usrmod1004_force_logoff;
+};
+
+struct USER_MODALS_INFO_1005 {
+ uint32_t usrmod1005_password_hist_len;
+};
+
+struct USER_MODALS_INFO_1006 {
+ uint32_t usrmod1006_role;
+};
+
+struct USER_MODALS_INFO_1007 {
+ const char * usrmod1007_primary;
+};
+
+struct NET_DISPLAY_USER {
+ const char * usri1_name;
+ const char * usri1_comment;
+ uint32_t usri1_flags;
+ const char * usri1_full_name;
+ uint32_t usri1_user_id;
+ uint32_t usri1_next_index;
+};
+
+struct NET_DISPLAY_MACHINE {
+ const char * usri2_name;
+ const char * usri2_comment;
+ uint32_t usri2_flags;
+ uint32_t usri2_user_id;
+ uint32_t usri2_next_index;
+};
+
+struct NET_DISPLAY_GROUP {
+ const char * grpi3_name;
+ const char * grpi3_comment;
+ uint32_t grpi3_group_id;
+ uint32_t grpi3_attributes;
+ uint32_t grpi3_next_index;
+};
+
+struct GROUP_INFO_0 {
+ const char * grpi0_name;
+};
+
+struct GROUP_INFO_1 {
+ const char * grpi1_name;
+ const char * grpi1_comment;
+};
+
+struct GROUP_INFO_2 {
+ const char * grpi2_name;
+ const char * grpi2_comment;
+ uint32_t grpi2_group_id;
+ uint32_t grpi2_attributes;
+};
+
+struct GROUP_INFO_3 {
+ const char * grpi3_name;
+ const char * grpi3_comment;
+ struct domsid * grpi3_group_sid;
+ uint32_t grpi3_attributes;
+};
+
+struct GROUP_INFO_1002 {
+ const char * grpi1002_comment;
+};
+
+struct GROUP_INFO_1005 {
+ uint32_t grpi1005_attributes;
+};
+
+struct GROUP_USERS_INFO_0 {
+ const char * grui0_name;
+};
+
+struct GROUP_USERS_INFO_1 {
+ const char * grui1_name;
+ uint32_t grui1_attributes;
+};
+
+struct LOCALGROUP_INFO_0 {
+ const char * lgrpi0_name;
+};
+
+struct LOCALGROUP_INFO_1 {
+ const char * lgrpi1_name;
+ const char * lgrpi1_comment;
+};
+
+struct LOCALGROUP_INFO_1002 {
+ const char * lgrpi1002_comment;
+};
+
+enum SID_NAME_USE {
+ SidTypeUser=1,
+ SidTypeGroup=2,
+ SidTypeDomain=3,
+ SidTypeAlias=4,
+ SidTypeWellKnownGroup=5,
+ SidTypeDeletedAccount=6,
+ SidTypeInvalid=7,
+ SidTypeUnknown=8,
+ SidTypeComputer=9,
+ SidTypeLabel=10
+};
+
+struct LOCALGROUP_MEMBERS_INFO_0 {
+ struct domsid *lgrmi0_sid;/* [unique] */
+};
+
+struct LOCALGROUP_MEMBERS_INFO_1 {
+ struct domsid *lgrmi1_sid;/* [unique] */
+ enum SID_NAME_USE lgrmi1_sidusage;
+ const char * lgrmi1_name;
+};
+
+struct LOCALGROUP_MEMBERS_INFO_2 {
+ struct domsid *lgrmi2_sid;/* [unique] */
+ enum SID_NAME_USE lgrmi2_sidusage;
+ const char * lgrmi2_domainandname;
+};
+
+struct LOCALGROUP_MEMBERS_INFO_3 {
+ const char * lgrmi3_domainandname;
+};
+
+struct LOCALGROUP_USERS_INFO_0 {
+ const char * lgrui0_name;
+};
+
+struct TIME_OF_DAY_INFO {
+ uint32_t tod_elapsedt;
+ uint32_t tod_msecs;
+ uint32_t tod_hours;
+ uint32_t tod_mins;
+ uint32_t tod_secs;
+ uint32_t tod_hunds;
+ int32_t tod_timezone;
+ uint32_t tod_tinterval;
+ uint32_t tod_day;
+ uint32_t tod_month;
+ uint32_t tod_year;
+ uint32_t tod_weekday;
+};
+
+struct SHARE_INFO_0 {
+ const char * shi0_netname;
+};
+
+struct SHARE_INFO_1 {
+ const char * shi1_netname;
+ uint32_t shi1_type;
+ const char * shi1_remark;
+};
+
+struct SHARE_INFO_2 {
+ const char * shi2_netname;
+ uint32_t shi2_type;
+ const char * shi2_remark;
+ uint32_t shi2_permissions;
+ uint32_t shi2_max_uses;
+ uint32_t shi2_current_uses;
+ const char * shi2_path;
+ const char * shi2_passwd;
+};
+
+struct SHARE_INFO_501 {
+ const char * shi501_netname;
+ uint32_t shi501_type;
+ const char * shi501_remark;
+ uint32_t shi501_flags;
+};
+
+struct SHARE_INFO_502 {
+ const char * shi502_netname;
+ uint32_t shi502_type;
+ const char * shi502_remark;
+ uint32_t shi502_permissions;
+ uint32_t shi502_max_uses;
+ uint32_t shi502_current_uses;
+ const char * shi502_path;
+ const char * shi502_passwd;
+ uint32_t shi502_reserved;
+ struct security_descriptor * shi502_security_descriptor;
+};
+
+struct SHARE_INFO_1004 {
+ const char * shi1004_remark;
+};
+
+struct SHARE_INFO_1005 {
+ uint32_t shi1005_flags;
+};
+
+struct SHARE_INFO_1006 {
+ uint32_t shi1006_max_uses;
+};
+
+struct FILE_INFO_2 {
+ uint32_t fi2_id;
+};
+
+struct FILE_INFO_3 {
+ uint32_t fi3_id;
+ uint32_t fi3_permissions;
+ uint32_t fi3_num_locks;
+ const char * fi3_pathname;
+ const char * fi3_username;
+};
+
+struct NETLOGON_INFO_1 {
+ uint32_t netlog1_flags;
+ NET_API_STATUS netlog1_pdc_connection_status;
+};
+
+struct NETLOGON_INFO_2 {
+ uint32_t netlog2_flags;
+ NET_API_STATUS netlog2_pdc_connection_status;
+ const char * netlog2_trusted_dc_name;
+ NET_API_STATUS netlog2_tc_connection_status;
+};
+
+struct NETLOGON_INFO_3 {
+ uint32_t netlog1_flags;
+ uint32_t netlog3_logon_attempts;
+ uint32_t netlog3_reserved1;
+ uint32_t netlog3_reserved2;
+ uint32_t netlog3_reserved3;
+ uint32_t netlog3_reserved4;
+ uint32_t netlog3_reserved5;
+};
+
+struct NETLOGON_INFO_4 {
+ const char * netlog4_trusted_dc_name;
+ const char * netlog4_trusted_domain_name;
+};
+
+#define DS_PDC_FLAG ( 0x00000001 )
+#define DS_GC_FLAG ( 0x00000004 )
+#define DS_LDAP_FLAG ( 0x00000008 )
+#define DS_DS_FLAG ( 0x00000010 )
+#define DS_KDC_FLAG ( 0x00000020 )
+#define DS_TIMESERV_FLAG ( 0x00000040 )
+#define DS_CLOSEST_FLAG ( 0x00000080 )
+#define DS_WRITABLE_FLAG ( 0x00000100 )
+#define DS_GOOD_TIMESERV_FLAG ( 0x00000200 )
+#define DS_NDNC_FLAG ( 0x00000400 )
+#define DS_SELECT_SECRET_DOMAIN_6_FLAG ( 0x00000800 )
+#define DS_FULL_SECRET_DOMAIN_6_FLAG ( 0x00001000 )
+#define DS_WS_FLAG ( 0x00002000 )
+#define DS_DS_8_FLAG ( 0x00004000 )
+#define DS_DNS_CONTROLLER_FLAG ( 0x20000000 )
+#define DS_DNS_DOMAIN_FLAG ( 0x40000000 )
+#define DS_DNS_FOREST_FLAG ( 0x80000000 )
+
+#endif /* _HEADER_libnetapi */
+
+#ifndef _HEADER_netlogon
+
+#define NETLOGON_CONTROL_QUERY ( 0x00000001 )
+#define NETLOGON_CONTROL_REPLICATE ( 0x00000002 )
+#define NETLOGON_CONTROL_SYNCHRONIZE ( 0x00000003 )
+#define NETLOGON_CONTROL_PDC_REPLICATE ( 0x00000004 )
+#define NETLOGON_CONTROL_REDISCOVER ( 0x00000005 )
+#define NETLOGON_CONTROL_TC_QUERY ( 0x00000006 )
+#define NETLOGON_CONTROL_TRANSPORT_NOTIFY ( 0x00000007 )
+#define NETLOGON_CONTROL_FIND_USER ( 0x00000008 )
+#define NETLOGON_CONTROL_CHANGE_PASSWORD ( 0x00000009 )
+#define NETLOGON_CONTROL_TC_VERIFY ( 0x0000000A )
+#define NETLOGON_CONTROL_FORCE_DNS_REG ( 0x0000000B )
+#define NETLOGON_CONTROL_QUERY_DNS_REG ( 0x0000000C )
+#define NETLOGON_CONTROL_BACKUP_CHANGE_LOG ( 0x0000FFFC )
+#define NETLOGON_CONTROL_TRUNCATE_LOG ( 0x0000FFFD )
+#define NETLOGON_CONTROL_SET_DBFLAG ( 0x0000FFFE )
+#define NETLOGON_CONTROL_BREAKPOINT ( 0x0000FFFF )
+
+#define DS_FORCE_REDISCOVERY ( 0x00000001 )
+#define DS_DIRECTORY_SERVICE_REQUIRED ( 0x00000010 )
+#define DS_DIRECTORY_SERVICE_PREFERRED ( 0x00000020 )
+#define DS_GC_SERVER_REQUIRED ( 0x00000040 )
+#define DS_PDC_REQUIRED ( 0x00000080 )
+#define DS_BACKGROUND_ONLY ( 0x00000100 )
+#define DS_IP_REQUIRED ( 0x00000200 )
+#define DS_KDC_REQUIRED ( 0x00000400 )
+#define DS_TIMESERV_REQUIRED ( 0x00000800 )
+#define DS_WRITABLE_REQUIRED ( 0x00001000 )
+#define DS_GOOD_TIMESERV_PREFERRED ( 0x00002000 )
+#define DS_AVOID_SELF ( 0x00004000 )
+#define DS_ONLY_LDAP_NEEDED ( 0x00008000 )
+#define DS_IS_FLAT_NAME ( 0x00010000 )
+#define DS_IS_DNS_NAME ( 0x00020000 )
+#define DS_TRY_NEXTCLOSEST_SITE ( 0x00040000 )
+#define DS_DIRECTORY_SERVICE_6_REQUIRED ( 0x00080000 )
+#define DS_WEB_SERVICE_REQUIRED ( 0x00100000 )
+#define DS_RETURN_DNS_NAME ( 0x40000000 )
+#define DS_RETURN_FLAT_NAME ( 0x80000000 )
+
+#endif /* _HEADER_netlogon */
+
+/****************************************************************
+****************************************************************/
+
+struct libnetapi_ctx;
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_init(struct libnetapi_ctx **ctx);
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx);
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx);
+
+NET_API_STATUS libnetapi_get_username(struct libnetapi_ctx *ctx,
+ const char **username);
+
+NET_API_STATUS libnetapi_get_password(struct libnetapi_ctx *ctx,
+ const char **password);
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx,
+ const char *debuglevel);
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_set_creds(struct libnetapi_ctx *ctx,
+ struct cli_credentials *creds);
+
+
+NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx,
+ const char *username);
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx,
+ const char *password);
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
+ const char *workgroup);
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_set_use_kerberos(struct libnetapi_ctx *ctx);
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_get_use_kerberos(struct libnetapi_ctx *ctx,
+ int *use_kerberos);
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_set_logfile(struct libnetapi_ctx *ctx,
+ const char *logfile);
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_set_use_ccache(struct libnetapi_ctx *ctx);
+
+/****************************************************************
+Return a specific libnetapi error as a string, caller must free with NetApiBufferFree
+****************************************************************/
+
+char *libnetapi_errstr(NET_API_STATUS status);
+
+/****************************************************************
+Return the last libnetapi error as a string, caller must free with NetApiBufferFree
+ctx is optional
+****************************************************************/
+
+char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
+ NET_API_STATUS status);
+
+/****************************************************************
+ NetApiBufferAllocate
+****************************************************************/
+
+NET_API_STATUS NetApiBufferAllocate(uint32_t byte_count,
+ void **buffer);
+
+/****************************************************************
+ NetApiBufferFree
+****************************************************************/
+
+NET_API_STATUS NetApiBufferFree(void *buffer);
+
+/************************************************************//**
+ *
+ * ConvertSidToStringSid
+ *
+ * @brief Convert a domain sid into a string
+ *
+ * @param[in] sid A pointer to a sid structure
+ * @param[in,out] sid_string A pointer that holds a pointer to a sid string. Caller
+ * needs to free with free(3)
+ * @return bool
+ ***************************************************************/
+
+int ConvertSidToStringSid(const struct domsid *sid,
+ char **sid_string);
+
+/************************************************************//**
+ *
+ * ConvertStringSidToSid
+ *
+ * @brief Convert a string into a domain sid
+ *
+ * @param[in] sid_string A pointer to a sid string.
+ * @param[in,out] sid A pointer that holds a pointer to a sid structure.
+ * Caller needs to free with free(3)
+ * @return bool
+ ***************************************************************/
+
+int ConvertStringSidToSid(const char *sid_string,
+ struct domsid **sid);
+
+/************************************************************//**
+ *
+ * NetJoinDomain
+ *
+ * @brief Join a computer to a domain or workgroup
+ *
+ * @param[in] server The server name to connect to
+ * @param[in] domain The domain or workgroup to join
+ * @param[in] account_ou The organizational Unit to create the computer account
+ * in (AD only)
+ * @param[in] account The domain account used for joining a domain
+ * @param[in] password The domain account's password used for joining a domain
+ * @param[in] join_flags Bitmask field to define specific join features
+ * @return NET_API_STATUS
+ *
+ * example netdomjoin/netdomjoin.c
+ ***************************************************************/
+
+NET_API_STATUS NetJoinDomain(const char * server /* [in] */,
+ const char * domain /* [in] [ref] */,
+ const char * account_ou /* [in] */,
+ const char * account /* [in] */,
+ const char * password /* [in] */,
+ uint32_t join_flags /* [in] */);
+
+/************************************************************//**
+ *
+ * NetUnjoinDomain
+ *
+ * @brief Unjoin a computer from a domain or workgroup
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] account The domain account used for unjoining a domain
+ * @param[in] password The domain account's password used for unjoining a domain
+ * @param[in] unjoin_flags Bitmask field to define specific unjoin features
+ * @return NET_API_STATUS
+ *
+ ***************************************************************/
+
+NET_API_STATUS NetUnjoinDomain(const char * server_name /* [in] */,
+ const char * account /* [in] */,
+ const char * password /* [in] */,
+ uint32_t unjoin_flags /* [in] */);
+
+/************************************************************//**
+ *
+ * NetGetJoinInformation
+ *
+ * @brief Unjoin a computer from a domain or workgroup
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[out] name_buffer Returns the name of the workgroup or domain
+ * @param[out] name_type Returns the type of that name
+ * @return NET_API_STATUS
+ *
+ * example netdomjoin-gui/netdomjoin-gui.c
+ *
+ ***************************************************************/
+
+NET_API_STATUS NetGetJoinInformation(const char * server_name /* [in] */,
+ const char * *name_buffer /* [out] [ref] */,
+ uint16_t *name_type /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetGetJoinableOUs
+ *
+ * @brief Query for the list of joinable organizational Units that can be used
+ * for joining AD
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] domain The AD domain to query
+ * @param[in] account The domain account used for the query
+ * @param[in] password The domain account's password used for the query
+ * @param[out] ou_count The number of ous returned
+ * @param[out] ous Returned string array containing the ous
+ * @return NET_API_STATUS
+ *
+ * example netdomjoin-gui/netdomjoin-gui.c
+ *
+ ***************************************************************/
+
+NET_API_STATUS NetGetJoinableOUs(const char * server_name /* [in] */,
+ const char * domain /* [in] [ref] */,
+ const char * account /* [in] */,
+ const char * password /* [in] */,
+ uint32_t *ou_count /* [out] [ref] */,
+ const char * **ous /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetRenameMachineInDomain
+ *
+ * @brief Rename a machine in a domain
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] new_machine_name The new machine name
+ * @param[in] account The domain account used for the query
+ * @param[in] password The domain account's password used for the query
+ * @param[in] rename_options Options used for the rename operation
+ * @return NET_API_STATUS
+ *
+ * example join/rename_machine.c
+ *
+ ***************************************************************/
+
+NET_API_STATUS NetRenameMachineInDomain(const char * server_name /* [in] */,
+ const char * new_machine_name /* [in] */,
+ const char * account /* [in] */,
+ const char * password /* [in] */,
+ uint32_t rename_options /* [in] */);
+
+/************************************************************//**
+ *
+ * NetProvisionComputerAccount
+ *
+ * @brief Provision a machine for offline join
+ *
+ * @param[in] domain The domain to provision for
+ * @param[in] machine_name The machine account name
+ * @param[in] machine_account_ou The machine account ou to create the account in
+ * @param[in] dcname A specific domain controller to use for account creation
+ * @param[in] options The options used for account creation
+ * @param[in,out] provision_bin_data The generated binary buffer
+ * @param[in,out] provision_bin_data_size The generated binary buffer size
+ * @param[in,out] provision_text_data The generated text data blob
+ * @return NET_API_STATUS
+ *
+ * example join/provision_computer_account.c
+ *
+ ***************************************************************/
+
+NET_API_STATUS NetProvisionComputerAccount(const char * domain /* [in] [ref] */,
+ const char * machine_name /* [in] [ref] */,
+ const char * machine_account_ou /* [in] [unique] */,
+ const char * dcname /* [in] [unique] */,
+ uint32_t options /* [in] */,
+ uint8_t **provision_bin_data /* [in,out] [unique] */,
+ uint32_t *provision_bin_data_size /* [in,out] [unique] */,
+ const char * *provision_text_data /* [in,out] [unique] */);
+
+/************************************************************//**
+ *
+ * NetRequestOfflineDomainJoin
+ *
+ * @brief Request an offline domain join
+ *
+ * @param[in] provision_bin_data The provided binary buffer
+ * @param[in] provision_bin_data_size The provided binary buffer size
+ * @param[in] options The options used for account creation
+ * @param[in] windows_path The path for the joined image
+ * @return NET_API_STATUS
+ *
+ * example join/request_offline_domain_join.c
+ *
+ ***************************************************************/
+
+NET_API_STATUS NetRequestOfflineDomainJoin(uint8_t *provision_bin_data /* [in] [unique] */,
+ uint32_t provision_bin_data_size /* [in] */,
+ uint32_t options /* [in] */,
+ const char * windows_path /* [in] [unique] */);
+
+/************************************************************//**
+ *
+ * NetServerGetInfo
+ *
+ * @brief Get Information on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level to define which information is requested
+ * @param[out] buffer The returned buffer carrying the SERVER_INFO structure
+ * @return NET_API_STATUS
+ *
+ ***************************************************************/
+
+NET_API_STATUS NetServerGetInfo(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetServerSetInfo
+ *
+ * @brief Get Information on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level to define which information is set
+ * @param[in] buffer The buffer carrying the SERVER_INFO structure
+ * @param[out] parm_error On failure returns the invalid SERVER_INFO member
+ * @return NET_API_STATUS
+ *
+ ***************************************************************/
+
+NET_API_STATUS NetServerSetInfo(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_error /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetWkstaGetInfo
+ *
+ * @brief Get Information on a workstation
+ *
+ * @param[in] wksta_name The workstation name to connect to
+ * @param[in] level The level to define which information is requested
+ * @param[out] buffer The returned buffer carrying the WKSTA_INFO structure
+ * @return NET_API_STATUS
+ *
+ ***************************************************************/
+
+NET_API_STATUS NetWkstaGetInfo(const char * wksta_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetGetDCName
+ *
+ * @brief Query for the PDC for a given domain
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] domain_name The name of the domain to lookup
+ * @param[out] buffer The name of the domain to lookup
+ * @return NET_API_STATUS
+ *
+ * example getdc/getdc.c
+ ***************************************************************/
+
+NET_API_STATUS NetGetDCName(const char * server_name /* [in] */,
+ const char * domain_name /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetGetAnyDCName
+ *
+ * @brief Query for any DC for a given domain
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] domain_name The name of the domain to lookup
+ * @param[out] buffer The name of the domain to lookup
+ * @return NET_API_STATUS
+ *
+ * example getdc/getdc.c
+ ***************************************************************/
+
+NET_API_STATUS NetGetAnyDCName(const char * server_name /* [in] */,
+ const char * domain_name /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+
+
+/************************************************************//**
+ *
+ * DsGetDcName
+ *
+ * @brief Lookup a DC for a given domain and return information structure
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] domain_name The name of the domain to lookup (cannot be NULL)
+ * @param[in] domain_guid The GUID of the domain to lookup (optional)
+ * @param[in] site_name The name of the site the DC should reside in
+ * @param[in] flags A bitmask to request specific features supported by the DC
+ * @param[out] dc_info Pointer to a DOMAIN_CONTROLLER_INFO structure
+ * @return NET_API_STATUS
+ *
+ * example dsgetdc/dsgetdc.c
+ ***************************************************************/
+
+NET_API_STATUS DsGetDcName(const char * server_name /* [in] [unique] */,
+ const char * domain_name /* [in] [ref] */,
+ struct GUID *domain_guid /* [in] [unique] */,
+ const char * site_name /* [in] [unique] */,
+ uint32_t flags /* [in] */,
+ struct DOMAIN_CONTROLLER_INFO **dc_info /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetUserAdd
+ *
+ * @brief Create a user on a given server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level of the USER_INFO structure passed in (Currently
+ * only level 1 is supported)
+ * @param[in] buffer The buffer carrying the USER_INFO structure
+ * @param[out] parm_error In case of error returns the failing member of the
+ * structure
+ * @return NET_API_STATUS
+ *
+ * example user/user_add.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_error /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetUserDel
+ *
+ * @brief Delete a user on a given server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] user_name The user account to delete
+ * @return NET_API_STATUS
+ *
+ * example user/user_del.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserDel(const char * server_name /* [in] */,
+ const char * user_name /* [in] */);
+
+/************************************************************//**
+ *
+ * NetUserEnum
+ *
+ * @brief Enumerate accounts on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The enumeration level used for the query (Currently only
+ * level 0 is supported)
+ * @param[in] filter The account flags filter used for the query
+ * @param[out] buffer The returned enumeration buffer
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of returned entries
+ * @param[out] total_entries The number of total entries
+ * @param[in,out] resume_handle A handle passed in and returned for resuming
+ * operations
+ * @return NET_API_STATUS
+ *
+ * example user/user_enum.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint32_t filter /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetUserChangePassword
+ *
+ * @brief Change the password for a user on a given server or in a given domain
+ *
+ * @param[in] domain_name The server or domain name to connect to
+ * @param[in] user_name The user account to change the password for
+ * @param[in] old_password The user account's old password
+ * @param[in] new_password The user account's new password
+ * @return NET_API_STATUS
+ *
+ * example user/user_chgpwd.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserChangePassword(const char * domain_name /* [in] */,
+ const char * user_name /* [in] */,
+ const char * old_password /* [in] */,
+ const char * new_password /* [in] */);
+
+/************************************************************//**
+ *
+ * NetUserGetInfo
+ *
+ * @brief Get User Information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] user_name The name of the user that is going to be queried
+ * @param[in] level The level defining the requested USER_INFO_X structure
+ * @param[out] buffer The buffer containing a USER_INFO_X structure
+ * @return NET_API_STATUS
+ *
+ * example user/user_getinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserGetInfo(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetUserSetInfo
+ *
+ * @brief Set User Information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] user_name The name of the user that is going to be modified
+ * @param[in] level The level defining the requested USER_INFO_X structure
+ * @param[in] buffer The buffer containing a USER_INFO_X structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example user/user_setinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserSetInfo(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetUserModalsGet
+ *
+ * @brief Get SAM domain and password information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level defining which USER_MODALS_INFO_X buffer to query
+ * @param[out] buffer The returned USER_MODALS_INFO_X buffer
+ * @return NET_API_STATUS
+ *
+ * example user/user_modalsget.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserModalsGet(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetUserModalsSet
+ *
+ * @brief Set SAM domain and password information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level defining which USER_MODALS_INFO_X buffer to query
+ * @param[out] buffer The buffer conntaing a USER_MODALS_INFO_X structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example user/user_modalsset.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserModalsSet(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetUserGetGroups
+ *
+ * @brief Enumerate grouplist of a user on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] user_name The user name to query
+ * @param[in] level The enumeration level used for the query (Currently only
+ * level 0 is supported)
+ * @param[out] buffer The returned enumeration buffer
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of returned entries
+ * @param[out] total_entries The number of total entries
+ * @return NET_API_STATUS
+ *
+ * example user/user_getgroups.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserGetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetUserSetGroups
+ *
+ * @brief Set grouplist of a user on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] user_name The user name to query
+ * @param[in] level The level defining the GROUP_USERS_INFO_X structures in the buffer
+ * @param[in] buffer The buffer containing GROUP_USERS_INFO_X structures
+ * @param[in] num_entries The number of X structures in the buffer
+ * @return NET_API_STATUS
+ *
+ * example user/user_setgroups.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserSetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t num_entries /* [in] */);
+
+/************************************************************//**
+ *
+ * NetUserGetLocalGroups
+ *
+ * @brief Enumerate local grouplist of a user on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] user_name The user name to query
+ * @param[in] level The enumeration level used for the query
+ * @param[in] flags The flags used for the query
+ * @param[out] buffer The returned enumeration buffer
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of returned entries
+ * @param[out] total_entries The number of total entries
+ * @return NET_API_STATUS
+ *
+ * example user/user_getlocalgroups.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserGetLocalGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint32_t flags /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetQueryDisplayInformation
+ *
+ * @brief Enumerate accounts on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The enumeration level used for the query
+ * @param[in] idx The index to start the the display enumeration at
+ * @param[in] entries_requested The number of entries requested
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of returned entries
+ * @param[out] buffer The returned display information buffer
+ * @return NET_API_STATUS
+ *
+ * example user/user_dispinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetQueryDisplayInformation(const char * server_name /* [in] [unique] */,
+ uint32_t level /* [in] */,
+ uint32_t idx /* [in] */,
+ uint32_t entries_requested /* [in] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ void **buffer /* [out] [noprint,ref] */);
+
+/************************************************************//**
+ *
+ * NetGroupAdd
+ *
+ * @brief Create Domain Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level used for the new group creation
+ * @param[in] buf The buffer containing the group structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example group/group_add.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buf /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetGroupDel
+ *
+ * @brief Delete Domain Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be deleted
+ * @return NET_API_STATUS
+ *
+ * example group/group_del.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupDel(const char * server_name /* [in] */,
+ const char * group_name /* [in] */);
+
+/************************************************************//**
+ *
+ * NetGroupEnum
+ *
+ * @brief Enumerate groups on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The enumeration level used for the query (Currently only
+ * level 0 is supported)
+ * @param[out] buffer The returned enumeration buffer
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of returned entries
+ * @param[out] total_entries The number of total entries
+ * @param[in,out] resume_handle A handle passed in and returned for resuming
+ * operations
+ * @return NET_API_STATUS
+ *
+ * example group/group_enum.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetGroupSetInfo
+ *
+ * @brief Set Domain Group Information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be modified
+ * @param[in] level The level defining the structure type in buf
+ * @param[in] buf The buffer containing a GROUP_INFO_X structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example group/group_setinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupSetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buf /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetGroupGetInfo
+ *
+ * @brief Get Domain Group Information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be queried
+ * @param[in] level The level defining the requested GROUP_INFO_X structure
+ * @param[out] buf The buffer containing a GROUP_INFO_X structure
+ * @return NET_API_STATUS
+ *
+ * example group/group_getinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupGetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buf /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetGroupAddUser
+ *
+ * @brief Add existing User to existing Domain Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be modified
+ * @param[in] user_name The name of the user that is going to be added to the
+ * group
+ * @return NET_API_STATUS
+ *
+ * example group/group_adduser.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupAddUser(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ const char * user_name /* [in] */);
+
+/************************************************************//**
+ *
+ * NetGroupDelUser
+ *
+ * @brief Remove User from Domain Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be modified
+ * @param[in] user_name The name of the user that is going to be removed from
+ * the group
+ * @return NET_API_STATUS
+ *
+ * example group/group_deluser.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupDelUser(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ const char * user_name /* [in] */);
+
+/************************************************************//**
+ *
+ * NetGroupGetUsers
+ *
+ * @brief Get Users for a group on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The group name to enumerate users for
+ * @param[in] level The enumeration level used for the query
+ * @param[out] buffer The returned enumeration buffer
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of returned entries
+ * @param[out] total_entries The number of total entries
+ * @param[in,out] resume_handle A handle passed in and returned for resuming
+ * operations
+ * @return NET_API_STATUS
+ *
+ * example group/group_getusers.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupGetUsers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetGroupSetUsers
+ *
+ * @brief Set Users for a group on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The group name to enumerate users for
+ * @param[in] level The enumeration level used for the query
+ * @param[in] buffer The buffer containing a X structure
+ * @param[in] num_entries The number of X entries in the buffer
+ * @return NET_API_STATUS
+ *
+ * example group/group_setusers.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupSetUsers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t num_entries /* [in] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupAdd
+ *
+ * @brief Create Local Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level used for the new group creation
+ * @param[in] buf The buffer containing the group structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_add.c
+ ***************************************************************/
+
+NET_API_STATUS NetLocalGroupAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buf /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupDel
+ *
+ * @brief Delete Local Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be deleted
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_del.c
+ ***************************************************************/
+
+
+NET_API_STATUS NetLocalGroupDel(const char * server_name /* [in] */,
+ const char * group_name /* [in] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupGetInfo
+ *
+ * @brief Get Local Group Information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be queried
+ * @param[in] level The level defining the requested LOCALGROUP_INFO_X structure
+ * @param[out] buf The buffer containing a LOCALGROUP_INFO_X structure
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_getinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetLocalGroupGetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buf /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupSetInfo
+ *
+ * @brief Set Local Group Information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be modified
+ * @param[in] level The level defining the requested LOCALGROUP_INFO_X structure
+ * @param[in] buf The buffer containing a LOCALGROUP_INFO_X structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_setinfo.c
+ ***************************************************************/
+
+
+NET_API_STATUS NetLocalGroupSetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buf /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupEnum
+ *
+ * @brief Enumerate local groups on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The enumeration level used for the query (Currently only
+ * level 0 is supported)
+ * @param[out] buffer The returned enumeration buffer
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of returned entries
+ * @param[out] total_entries The number of total entries
+ * @param[in,out] resume_handle A handle passed in and returned for resuming
+ * operations
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_enum.c
+ ***************************************************************/
+
+NET_API_STATUS NetLocalGroupEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupAddMembers
+ *
+ * @brief Add Members to a Local Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to modified
+ * @param[in] level The level defining the LOCALGROUP_MEMBERS_INFO_X structure
+ * @param[in] buffer The buffer containing a LOCALGROUP_MEMBERS_INFO_X structure
+ * @param[in] total_entries The number of LOCALGROUP_MEMBERS_INFO_X entries in
+ * the buffer
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_addmembers.c
+ ***************************************************************/
+
+NET_API_STATUS NetLocalGroupAddMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupDelMembers
+ *
+ * @brief Delete Members from a Local Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to modified
+ * @param[in] level The level defining the LOCALGROUP_MEMBERS_INFO_X structure
+ * @param[in] buffer The buffer containing a LOCALGROUP_MEMBERS_INFO_X structure
+ * @param[in] total_entries The number of LOCALGROUP_MEMBERS_INFO_X entries in
+ * the buffer
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_delmembers.c
+ ***************************************************************/
+
+NET_API_STATUS NetLocalGroupDelMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupGetMembers
+ *
+ * @brief Enumerate Members in a local group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] local_group_name The localgroup that is going to be queried
+ * @param[in] level The level defining the LOCALGROUP_MEMBERS_INFO_X structure
+ * @param[out] buffer The buffer containing a LOCALGROUP_MEMBERS_INFO_X
+ * structure
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of LOCALGROUP_MEMBERS_INFO_X entries in the buffer
+ * @param[out] total_entries The total number of LOCALGROUP_MEMBERS_INFO_X entries for that group
+ * @param[in,out] resume_handle A handle passed in and returned for resuming
+ * operations
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_getmembers.c
+ ***************************************************************/
+
+NET_API_STATUS NetLocalGroupGetMembers(const char * server_name /* [in] */,
+ const char * local_group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupSetMembers
+ *
+ * @brief Set Members in a Local Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to modified
+ * @param[in] level The level defining the LOCALGROUP_MEMBERS_INFO_X structure
+ * @param[in] buffer The buffer containing a LOCALGROUP_MEMBERS_INFO_X structure
+ * @param[in] total_entries The number of LOCALGROUP_MEMBERS_INFO_X entries in
+ * the buffer
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_setmembers.c
+ ***************************************************************/
+
+NET_API_STATUS NetLocalGroupSetMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */);
+
+/************************************************************//**
+ *
+ * NetRemoteTOD
+ *
+ * @brief Query remote Time of Day
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[out] buf The buffer containing a TIME_OF_DAY_INFO structure
+ * @return NET_API_STATUS
+ *
+ * example server/remote_tod.c
+ ***************************************************************/
+
+NET_API_STATUS NetRemoteTOD(const char * server_name /* [in] */,
+ uint8_t **buf /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetShareAdd
+ *
+ * @brief Add Share
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level defining the requested SHARE_INFO_X structure
+ * @param[in] buffer The buffer containing a SHARE_INFO_X structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example share/share_add.c
+ ***************************************************************/
+
+NET_API_STATUS NetShareAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetShareDel
+ *
+ * @brief Delete Share
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] net_name The name of the share to delete
+ * @param[in] reserved
+ * @return NET_API_STATUS
+ *
+ * example share/share_del.c
+ ***************************************************************/
+
+NET_API_STATUS NetShareDel(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t reserved /* [in] */);
+
+/************************************************************//**
+ *
+ * NetShareEnum
+ *
+ * @brief Enumerate Shares
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level defining the SHARE_INFO_X structure
+ * @param[out] buffer The buffer containing a SHARE_INFO_X structure
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of SHARE_INFO_X entries in the buffer
+ * @param[out] total_entries The total number of SHARE_INFO_X entries
+ * @param[in,out] resume_handle A handle passed in and returned for resuming
+ * operations
+ * @return NET_API_STATUS
+ *
+ * example share/share_enum.c
+ ***************************************************************/
+
+NET_API_STATUS NetShareEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetShareGetInfo
+ *
+ * @brief Get Share Info
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] net_name The name of the share to query
+ * @param[in] level The level defining the SHARE_INFO_X structure
+ * @param[out] buffer The buffer containing a SHARE_INFO_X structure
+ * @return NET_API_STATUS
+ *
+ * example share/share_getinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetShareGetInfo(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetShareSetInfo
+ *
+ * @brief Set Share Info
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] net_name The name of the share to query
+ * @param[in] level The level defining the SHARE_INFO_X structure
+ * @param[in] buffer The buffer containing a SHARE_INFO_X structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example share/share_setinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetShareSetInfo(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetFileClose
+ *
+ * @brief Close a file
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] fileid The fileid of the file that is going to be closed
+ * @return NET_API_STATUS
+ *
+ * example file/file_close.c
+ ***************************************************************/
+
+NET_API_STATUS NetFileClose(const char * server_name /* [in] */,
+ uint32_t fileid /* [in] */);
+
+/************************************************************//**
+ *
+ * NetFileGetInfo
+ *
+ * @brief Close a file
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] fileid The fileid of the file that is going to be closed
+ * @param[in] level The level of the FILE_INFO_X buffer
+ * @param[out] buffer The buffer containing a FILE_INFO_X structure
+ * @return NET_API_STATUS
+ *
+ * example file/file_getinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetFileGetInfo(const char * server_name /* [in] */,
+ uint32_t fileid /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetFileEnum
+ *
+ * @brief Enumerate Files
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] base_path The
+ * @param[in] user_name The
+ * @param[in] level The level defining the FILE_INFO_X structure
+ * @param[out] buffer The buffer containing a FILE_INFO_X structure
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of FILE_INFO_X entries in the buffer
+ * @param[out] total_entries The total number of FILE_INFO_X entries
+ * @param[in,out] resume_handle A handle passed in and returned for resuming
+ * operations
+ * @return NET_API_STATUS
+ *
+ * example file/file_enum.c
+ ***************************************************************/
+
+NET_API_STATUS NetFileEnum(const char * server_name /* [in] */,
+ const char * base_path /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetShutdownInit
+ *
+ * @brief Start a machine shutdown
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] message The message that is displayed before the shutdown
+ * @param[in] timeout The amount of seconds to wait until shutting down
+ * @param[in] force_apps Whether to close all applications before the shutdown
+ * @param[in] do_reboot Whether to reboot after the shutdown
+ * @return NET_API_STATUS
+ *
+ * example shutdown/shutdown_init.c
+ ***************************************************************/
+
+NET_API_STATUS NetShutdownInit(const char * server_name /* [in] */,
+ const char * message /* [in] */,
+ uint32_t timeout /* [in] */,
+ uint8_t force_apps /* [in] */,
+ uint8_t do_reboot /* [in] */);
+
+/************************************************************//**
+ *
+ * NetShutdownAbort
+ *
+ * @brief Abort an initiated machine shutdown
+ *
+ * @param[in] server_name The server name to connect to
+ * @return NET_API_STATUS
+ *
+ * example shutdown/shutdown_abort.c
+ ***************************************************************/
+
+NET_API_STATUS NetShutdownAbort(const char * server_name /* [in] */);
+
+/************************************************************//**
+ *
+ * I_NetLogonControl
+ *
+ * @brief Control various aspects of the NETLOGON service
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] function_code The function code to call on the server
+ * @param[in] query_level The level of the NETLOGON_INFO structure returned
+ * @param[out] buffer The returned buffer containing the NETLOGON_INFO structure
+ * @return NET_API_STATUS
+ *
+ * example netlogon/netlogon_control.c
+ ***************************************************************/
+
+NET_API_STATUS I_NetLogonControl(const char * server_name /* [in] */,
+ uint32_t function_code /* [in] */,
+ uint32_t query_level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * I_NetLogonControl2
+ *
+ * @brief Control various aspects of the NETLOGON service
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] function_code The function code to call on the server
+ * @param[in] query_level The level of the NETLOGON_INFO structure returned
+ * @param[in] data The buffer containing information related to the function code
+ * @param[out] buffer The returned buffer containing the NETLOGON_INFO structure
+ * @return NET_API_STATUS
+ *
+ * example netlogon/netlogon_control2.c
+ ***************************************************************/
+
+NET_API_STATUS I_NetLogonControl2(const char * server_name /* [in] */,
+ uint32_t function_code /* [in] */,
+ uint32_t query_level /* [in] */,
+ uint8_t *data /* [in] [ref] */,
+ uint8_t **buffer /* [out] [ref] */);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LIB_NETAPI_H__ */
diff --git a/source3/lib/netapi/netapi_net.h b/source3/lib/netapi/netapi_net.h
new file mode 100644
index 0000000..c1b06ad
--- /dev/null
+++ b/source3/lib/netapi/netapi_net.h
@@ -0,0 +1,24 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Support
+ * Copyright (C) Andrew Bartlett 2010
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* This API header is private between the 'net' binary and and libnet */
+
+/* This function is to init the libnetapi subsystem, without
+ * re-reading config files or setting debug levels etc */
+NET_API_STATUS libnetapi_net_init(struct libnetapi_ctx **ctx);
diff --git a/source3/lib/netapi/netapi_private.h b/source3/lib/netapi/netapi_private.h
new file mode 100644
index 0000000..5cfd8d0
--- /dev/null
+++ b/source3/lib/netapi/netapi_private.h
@@ -0,0 +1,113 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Support
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LIB_NETAPI_PRIVATE_H__
+#define __LIB_NETAPI_PRIVATE_H__
+
+#include "lib/netapi/netapi_net.h"
+#include "auth/credentials/credentials.h"
+
+#define LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, fn) \
+ DEBUG(10,("redirecting call %s to localhost\n", #fn)); \
+ if (!r->in.server_name) { \
+ r->in.server_name = "localhost"; \
+ } \
+ return fn ## _r(ctx, r);
+
+struct dcerpc_binding_handle;
+struct ndr_interface_table;
+
+struct libnetapi_private_ctx {
+ struct {
+ const char *domain_name;
+ struct dom_sid *domain_sid;
+ struct rpc_pipe_client *cli;
+
+ uint32_t connect_mask;
+ struct policy_handle connect_handle;
+
+ uint32_t domain_mask;
+ struct policy_handle domain_handle;
+
+ uint32_t builtin_mask;
+ struct policy_handle builtin_handle;
+ } samr;
+
+ struct client_ipc_connection *ipc_connections;
+
+ struct messaging_context *msg_ctx;
+};
+
+struct libnetapi_ctx {
+ char *debuglevel;
+ char *logfile;
+ char *error_string;
+ int disable_policy_handle_cache;
+
+ struct cli_credentials *creds;
+
+ void *private_data;
+};
+
+
+NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx,
+ const char *format, ...)
+ PRINTF_ATTRIBUTE(2,3);
+NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx, char **debuglevel);
+NET_API_STATUS libnetapi_set_logfile(struct libnetapi_ctx *ctx,
+ const char *logfile);
+
+WERROR libnetapi_shutdown_cm(struct libnetapi_ctx *ctx);
+WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const struct ndr_interface_table *table,
+ struct rpc_pipe_client **presult);
+WERROR libnetapi_get_binding_handle(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const struct ndr_interface_table *table,
+ struct dcerpc_binding_handle **binding_handle);
+WERROR libnetapi_samr_open_domain(struct libnetapi_ctx *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ uint32_t connect_mask,
+ uint32_t domain_mask,
+ struct policy_handle *connect_handle,
+ struct policy_handle *domain_handle,
+ struct dom_sid2 **domain_sid);
+WERROR libnetapi_samr_open_builtin_domain(struct libnetapi_ctx *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ uint32_t connect_mask,
+ uint32_t builtin_mask,
+ struct policy_handle *connect_handle,
+ struct policy_handle *builtin_handle);
+void libnetapi_samr_close_domain_handle(struct libnetapi_ctx *ctx,
+ struct policy_handle *handle);
+void libnetapi_samr_close_builtin_handle(struct libnetapi_ctx *ctx,
+ struct policy_handle *handle);
+void libnetapi_samr_close_connect_handle(struct libnetapi_ctx *ctx,
+ struct policy_handle *handle);
+void libnetapi_samr_free(struct libnetapi_ctx *ctx);
+
+NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ const char *group_name,
+ uint32_t attributes,
+ uint8_t **buffer,
+ uint32_t *num_entries);
+
+#endif
diff --git a/source3/lib/netapi/netlogon.c b/source3/lib/netapi/netlogon.c
new file mode 100644
index 0000000..717dd17
--- /dev/null
+++ b/source3/lib/netapi/netlogon.c
@@ -0,0 +1,248 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi LogonControl Support
+ * Copyright (C) Guenther Deschner 2009
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "../librpc/gen_ndr/ndr_netlogon_c.h"
+#include "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+
+static WERROR construct_data(enum netr_LogonControlCode function_code,
+ const uint8_t *data_in,
+ union netr_CONTROL_DATA_INFORMATION *data_out)
+{
+ switch (function_code) {
+ case NETLOGON_CONTROL_QUERY:
+ case NETLOGON_CONTROL_REDISCOVER:
+ case NETLOGON_CONTROL_TC_QUERY:
+ case NETLOGON_CONTROL_CHANGE_PASSWORD:
+ case NETLOGON_CONTROL_TC_VERIFY:
+ data_out->domain = (const char *)data_in;
+ break;
+ case NETLOGON_CONTROL_FIND_USER:
+ data_out->user = (const char *)data_in;
+ break;
+ case NETLOGON_CONTROL_SET_DBFLAG:
+ data_out->debug_level = atoi((const char *)data_in);
+ break;
+ case NETLOGON_CONTROL_FORCE_DNS_REG:
+ ZERO_STRUCTP(data_out);
+ break;
+ default:
+ return WERR_INVALID_PARAMETER;
+ }
+
+ return WERR_OK;
+}
+
+static WERROR construct_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ union netr_CONTROL_QUERY_INFORMATION *q,
+ uint8_t **buffer)
+{
+ struct NETLOGON_INFO_1 *i1;
+ struct NETLOGON_INFO_2 *i2;
+ struct NETLOGON_INFO_3 *i3;
+ struct NETLOGON_INFO_4 *i4;
+
+ if (!q) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (level) {
+ case 1:
+ i1 = talloc(mem_ctx, struct NETLOGON_INFO_1);
+ W_ERROR_HAVE_NO_MEMORY(i1);
+
+ i1->netlog1_flags = q->info1->flags;
+ i1->netlog1_pdc_connection_status = W_ERROR_V(q->info1->pdc_connection_status);
+
+ *buffer = (uint8_t *)i1;
+
+ break;
+ case 2:
+ i2 = talloc(mem_ctx, struct NETLOGON_INFO_2);
+ W_ERROR_HAVE_NO_MEMORY(i2);
+
+ i2->netlog2_flags = q->info2->flags;
+ i2->netlog2_pdc_connection_status = W_ERROR_V(q->info2->pdc_connection_status);
+ i2->netlog2_trusted_dc_name = talloc_strdup(mem_ctx, q->info2->trusted_dc_name);
+ i2->netlog2_tc_connection_status = W_ERROR_V(q->info2->tc_connection_status);
+
+ *buffer = (uint8_t *)i2;
+
+ break;
+ case 3:
+ i3 = talloc(mem_ctx, struct NETLOGON_INFO_3);
+ W_ERROR_HAVE_NO_MEMORY(i3);
+
+ i3->netlog1_flags = q->info3->flags;
+ i3->netlog3_logon_attempts = q->info3->logon_attempts;
+ i3->netlog3_reserved1 = q->info3->unknown1;
+ i3->netlog3_reserved2 = q->info3->unknown2;
+ i3->netlog3_reserved3 = q->info3->unknown3;
+ i3->netlog3_reserved4 = q->info3->unknown4;
+ i3->netlog3_reserved5 = q->info3->unknown5;
+
+ *buffer = (uint8_t *)i3;
+
+ break;
+ case 4:
+ i4 = talloc(mem_ctx, struct NETLOGON_INFO_4);
+ W_ERROR_HAVE_NO_MEMORY(i4);
+
+ i4->netlog4_trusted_dc_name = talloc_strdup(mem_ctx, q->info4->trusted_dc_name);
+ i4->netlog4_trusted_domain_name = talloc_strdup(mem_ctx, q->info4->trusted_domain_name);
+
+ *buffer = (uint8_t *)i4;
+
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR I_NetLogonControl_r(struct libnetapi_ctx *ctx,
+ struct I_NetLogonControl *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ union netr_CONTROL_QUERY_INFORMATION query;
+ struct dcerpc_binding_handle *b;
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_netlogon,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_netr_LogonControl(b, talloc_tos(),
+ r->in.server_name,
+ r->in.function_code,
+ r->in.query_level,
+ &query,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = construct_buffer(ctx, r->in.query_level, &query,
+ r->out.buffer);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR I_NetLogonControl_l(struct libnetapi_ctx *ctx,
+ struct I_NetLogonControl *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, I_NetLogonControl);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR I_NetLogonControl2_r(struct libnetapi_ctx *ctx,
+ struct I_NetLogonControl2 *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ union netr_CONTROL_DATA_INFORMATION data;
+ union netr_CONTROL_QUERY_INFORMATION query;
+ struct dcerpc_binding_handle *b;
+
+ werr = construct_data(r->in.function_code, r->in.data, &data);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_netlogon,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ switch (r->in.function_code) {
+ case NETLOGON_CONTROL_TC_VERIFY:
+ case NETLOGON_CONTROL_SET_DBFLAG:
+ case NETLOGON_CONTROL_FORCE_DNS_REG:
+ status = dcerpc_netr_LogonControl2Ex(b, talloc_tos(),
+ r->in.server_name,
+ r->in.function_code,
+ r->in.query_level,
+ &data,
+ &query,
+ &werr);
+ break;
+ default:
+ status = dcerpc_netr_LogonControl2(b, talloc_tos(),
+ r->in.server_name,
+ r->in.function_code,
+ r->in.query_level,
+ &data,
+ &query,
+ &werr);
+ break;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = construct_buffer(ctx, r->in.query_level, &query,
+ r->out.buffer);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR I_NetLogonControl2_l(struct libnetapi_ctx *ctx,
+ struct I_NetLogonControl2 *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, I_NetLogonControl2);
+}
diff --git a/source3/lib/netapi/samr.c b/source3/lib/netapi/samr.c
new file mode 100644
index 0000000..c1b7cfa
--- /dev/null
+++ b/source3/lib/netapi/samr.c
@@ -0,0 +1,346 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Samr Support
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "rpc_client/rpc_client.h"
+#include "../librpc/gen_ndr/ndr_samr_c.h"
+#include "rpc_client/cli_samr.h"
+#include "rpc_client/init_lsa.h"
+#include "../libcli/security/security.h"
+
+/****************************************************************
+****************************************************************/
+
+WERROR libnetapi_samr_open_domain(struct libnetapi_ctx *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ uint32_t connect_mask,
+ uint32_t domain_mask,
+ struct policy_handle *connect_handle,
+ struct policy_handle *domain_handle,
+ struct dom_sid2 **domain_sid)
+{
+ NTSTATUS status, result;
+ WERROR werr;
+ struct libnetapi_private_ctx *priv;
+ uint32_t resume_handle = 0;
+ uint32_t num_entries = 0;
+ struct samr_SamArray *sam = NULL;
+ const char *domain_name = NULL;
+ struct lsa_String lsa_domain_name;
+ bool domain_found = false;
+ int i;
+ struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
+
+ priv = talloc_get_type_abort(mem_ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ if (is_valid_policy_hnd(&priv->samr.connect_handle)) {
+ if ((priv->samr.connect_mask & connect_mask) == connect_mask) {
+ *connect_handle = priv->samr.connect_handle;
+ } else {
+ libnetapi_samr_close_connect_handle(mem_ctx,
+ &priv->samr.connect_handle);
+ }
+ }
+
+ if (is_valid_policy_hnd(&priv->samr.domain_handle)) {
+ if ((priv->samr.domain_mask & domain_mask) == domain_mask) {
+ *domain_handle = priv->samr.domain_handle;
+ } else {
+ libnetapi_samr_close_domain_handle(mem_ctx,
+ &priv->samr.domain_handle);
+ }
+ }
+
+ if (priv->samr.domain_sid) {
+ *domain_sid = priv->samr.domain_sid;
+ }
+
+ if (is_valid_policy_hnd(&priv->samr.connect_handle) &&
+ ((priv->samr.connect_mask & connect_mask) == connect_mask) &&
+ is_valid_policy_hnd(&priv->samr.domain_handle) &&
+ (priv->samr.domain_mask & domain_mask) == domain_mask) {
+ return WERR_OK;
+ }
+
+ if (!is_valid_policy_hnd(connect_handle)) {
+ status = dcerpc_try_samr_connects(pipe_cli->binding_handle, mem_ctx,
+ pipe_cli->srv_name_slash,
+ connect_mask,
+ connect_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ status = dcerpc_samr_EnumDomains(b, mem_ctx,
+ connect_handle,
+ &resume_handle,
+ &sam,
+ 0xffffffff,
+ &num_entries,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ for (i=0; i<num_entries; i++) {
+
+ domain_name = sam->entries[i].name.string;
+
+ if (strequal(domain_name, builtin_domain_name())) {
+ continue;
+ }
+
+ domain_found = true;
+ break;
+ }
+
+ if (!domain_found) {
+ werr = WERR_NO_SUCH_DOMAIN;
+ goto done;
+ }
+
+ init_lsa_String(&lsa_domain_name, domain_name);
+
+ status = dcerpc_samr_LookupDomain(b, mem_ctx,
+ connect_handle,
+ &lsa_domain_name,
+ domain_sid,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = dcerpc_samr_OpenDomain(b, mem_ctx,
+ connect_handle,
+ domain_mask,
+ *domain_sid,
+ domain_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ priv->samr.cli = pipe_cli;
+
+ priv->samr.domain_name = domain_name;
+ priv->samr.domain_sid = *domain_sid;
+
+ priv->samr.connect_mask = connect_mask;
+ priv->samr.connect_handle = *connect_handle;
+
+ priv->samr.domain_mask = domain_mask;
+ priv->samr.domain_handle = *domain_handle;
+
+ werr = WERR_OK;
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR libnetapi_samr_open_builtin_domain(struct libnetapi_ctx *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ uint32_t connect_mask,
+ uint32_t builtin_mask,
+ struct policy_handle *connect_handle,
+ struct policy_handle *builtin_handle)
+{
+ NTSTATUS status, result;
+ WERROR werr;
+ struct libnetapi_private_ctx *priv;
+ struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
+
+ priv = talloc_get_type_abort(mem_ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ if (is_valid_policy_hnd(&priv->samr.connect_handle)) {
+ if ((priv->samr.connect_mask & connect_mask) == connect_mask) {
+ *connect_handle = priv->samr.connect_handle;
+ } else {
+ libnetapi_samr_close_connect_handle(mem_ctx,
+ &priv->samr.connect_handle);
+ }
+ }
+
+ if (is_valid_policy_hnd(&priv->samr.builtin_handle)) {
+ if ((priv->samr.builtin_mask & builtin_mask) == builtin_mask) {
+ *builtin_handle = priv->samr.builtin_handle;
+ } else {
+ libnetapi_samr_close_builtin_handle(mem_ctx,
+ &priv->samr.builtin_handle);
+ }
+ }
+
+ if (is_valid_policy_hnd(&priv->samr.connect_handle) &&
+ ((priv->samr.connect_mask & connect_mask) == connect_mask) &&
+ is_valid_policy_hnd(&priv->samr.builtin_handle) &&
+ (priv->samr.builtin_mask & builtin_mask) == builtin_mask) {
+ return WERR_OK;
+ }
+
+ if (!is_valid_policy_hnd(connect_handle)) {
+ status = dcerpc_try_samr_connects(pipe_cli->binding_handle, mem_ctx,
+ pipe_cli->srv_name_slash,
+ connect_mask,
+ connect_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ status = dcerpc_samr_OpenDomain(b, mem_ctx,
+ connect_handle,
+ builtin_mask,
+ discard_const_p(struct dom_sid, &global_sid_Builtin),
+ builtin_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ priv->samr.cli = pipe_cli;
+
+ priv->samr.connect_mask = connect_mask;
+ priv->samr.connect_handle = *connect_handle;
+
+ priv->samr.builtin_mask = builtin_mask;
+ priv->samr.builtin_handle = *builtin_handle;
+
+ werr = WERR_OK;
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+void libnetapi_samr_close_domain_handle(struct libnetapi_ctx *ctx,
+ struct policy_handle *handle)
+{
+ struct libnetapi_private_ctx *priv;
+ struct dcerpc_binding_handle *b;
+ NTSTATUS result;
+
+ if (!is_valid_policy_hnd(handle)) {
+ return;
+ }
+
+ priv = talloc_get_type_abort(ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ if (!ndr_policy_handle_equal(handle, &priv->samr.domain_handle)) {
+ return;
+ }
+
+ b = priv->samr.cli->binding_handle;
+
+ dcerpc_samr_Close(b, ctx, handle, &result);
+
+ ZERO_STRUCT(priv->samr.domain_handle);
+}
+
+/****************************************************************
+****************************************************************/
+
+void libnetapi_samr_close_builtin_handle(struct libnetapi_ctx *ctx,
+ struct policy_handle *handle)
+{
+ struct libnetapi_private_ctx *priv;
+ struct dcerpc_binding_handle *b;
+ NTSTATUS result;
+
+ if (!is_valid_policy_hnd(handle)) {
+ return;
+ }
+
+ priv = talloc_get_type_abort(ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ if (!ndr_policy_handle_equal(handle, &priv->samr.builtin_handle)) {
+ return;
+ }
+
+ b = priv->samr.cli->binding_handle;
+
+ dcerpc_samr_Close(b, ctx, handle, &result);
+
+ ZERO_STRUCT(priv->samr.builtin_handle);
+}
+
+/****************************************************************
+****************************************************************/
+
+void libnetapi_samr_close_connect_handle(struct libnetapi_ctx *ctx,
+ struct policy_handle *handle)
+{
+ struct libnetapi_private_ctx *priv;
+ struct dcerpc_binding_handle *b;
+ NTSTATUS result;
+
+ if (!is_valid_policy_hnd(handle)) {
+ return;
+ }
+
+ priv = talloc_get_type_abort(ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ if (!ndr_policy_handle_equal(handle, &priv->samr.connect_handle)) {
+ return;
+ }
+
+ b = priv->samr.cli->binding_handle;
+
+ dcerpc_samr_Close(b, ctx, handle, &result);
+
+ ZERO_STRUCT(priv->samr.connect_handle);
+}
+
+/****************************************************************
+****************************************************************/
+
+void libnetapi_samr_free(struct libnetapi_ctx *ctx)
+{
+ struct libnetapi_private_ctx *priv;
+
+ if (!ctx->private_data) {
+ return;
+ }
+
+ priv = talloc_get_type_abort(ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ libnetapi_samr_close_domain_handle(ctx, &priv->samr.domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &priv->samr.builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &priv->samr.connect_handle);
+}
diff --git a/source3/lib/netapi/serverinfo.c b/source3/lib/netapi/serverinfo.c
new file mode 100644
index 0000000..cb5d9a2
--- /dev/null
+++ b/source3/lib/netapi/serverinfo.c
@@ -0,0 +1,701 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Server Support
+ * Copyright (C) Guenther Deschner 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+#include "../librpc/gen_ndr/ndr_srvsvc_c.h"
+#include "lib/smbconf/smbconf.h"
+#include "lib/smbconf/smbconf_reg.h"
+#include "libsmb/dsgetdcname.h"
+
+/****************************************************************
+****************************************************************/
+
+static WERROR NetServerGetInfo_l_101(struct libnetapi_ctx *ctx,
+ uint8_t **buffer)
+{
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
+ struct SERVER_INFO_101 i;
+
+ i.sv101_platform_id = PLATFORM_ID_NT;
+ i.sv101_name = lp_netbios_name();
+ i.sv101_version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
+ i.sv101_version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
+ i.sv101_type = lp_default_server_announce();
+ i.sv101_comment = lp_server_string(ctx, lp_sub);
+
+ *buffer = (uint8_t *)talloc_memdup(ctx, &i, sizeof(i));
+ if (!*buffer) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR NetServerGetInfo_l_1005(struct libnetapi_ctx *ctx,
+ uint8_t **buffer)
+{
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
+ struct SERVER_INFO_1005 info1005;
+
+ info1005.sv1005_comment = lp_server_string(ctx, lp_sub);
+ *buffer = (uint8_t *)talloc_memdup(ctx, &info1005, sizeof(info1005));
+ if (!*buffer) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetServerGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetServerGetInfo *r)
+{
+ switch (r->in.level) {
+ case 101:
+ return NetServerGetInfo_l_101(ctx, r->out.buffer);
+ case 1005:
+ return NetServerGetInfo_l_1005(ctx, r->out.buffer);
+ default:
+ break;
+ }
+
+ return WERR_INVALID_LEVEL;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS map_server_info_to_SERVER_INFO_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ union srvsvc_NetSrvInfo *i,
+ uint8_t **buffer)
+{
+ struct SERVER_INFO_100 i100;
+ struct SERVER_INFO_101 i101;
+ struct SERVER_INFO_102 i102;
+ struct SERVER_INFO_402 i402;
+ struct SERVER_INFO_403 i403;
+ struct SERVER_INFO_502 i502;
+ struct SERVER_INFO_503 i503;
+ struct SERVER_INFO_599 i599;
+ struct SERVER_INFO_1005 i1005;
+#if 0
+ struct SERVER_INFO_1010 i1010;
+ struct SERVER_INFO_1016 i1016;
+ struct SERVER_INFO_1017 i1017;
+ struct SERVER_INFO_1018 i1018;
+ struct SERVER_INFO_1107 i1107;
+ struct SERVER_INFO_1501 i1501;
+ struct SERVER_INFO_1502 i1502;
+ struct SERVER_INFO_1503 i1503;
+ struct SERVER_INFO_1506 i1506;
+ struct SERVER_INFO_1509 i1509;
+ struct SERVER_INFO_1510 i1510;
+ struct SERVER_INFO_1511 i1511;
+ struct SERVER_INFO_1512 i1512;
+ struct SERVER_INFO_1513 i1513;
+ struct SERVER_INFO_1514 i1514;
+ struct SERVER_INFO_1515 i1515;
+ struct SERVER_INFO_1516 i1516;
+ struct SERVER_INFO_1518 i1518;
+ struct SERVER_INFO_1520 i1520;
+ struct SERVER_INFO_1521 i1521;
+ struct SERVER_INFO_1522 i1522;
+ struct SERVER_INFO_1523 i1523;
+ struct SERVER_INFO_1524 i1524;
+ struct SERVER_INFO_1525 i1525;
+ struct SERVER_INFO_1528 i1528;
+ struct SERVER_INFO_1529 i1529;
+ struct SERVER_INFO_1530 i1530;
+ struct SERVER_INFO_1533 i1533;
+ struct SERVER_INFO_1534 i1534;
+ struct SERVER_INFO_1535 i1535;
+ struct SERVER_INFO_1536 i1536;
+ struct SERVER_INFO_1537 i1537;
+ struct SERVER_INFO_1538 i1538;
+ struct SERVER_INFO_1539 i1539;
+ struct SERVER_INFO_1540 i1540;
+ struct SERVER_INFO_1541 i1541;
+ struct SERVER_INFO_1542 i1542;
+ struct SERVER_INFO_1543 i1543;
+ struct SERVER_INFO_1544 i1544;
+ struct SERVER_INFO_1545 i1545;
+ struct SERVER_INFO_1546 i1546;
+ struct SERVER_INFO_1547 i1547;
+ struct SERVER_INFO_1548 i1548;
+ struct SERVER_INFO_1549 i1549;
+ struct SERVER_INFO_1550 i1550;
+ struct SERVER_INFO_1552 i1552;
+ struct SERVER_INFO_1553 i1553;
+ struct SERVER_INFO_1554 i1554;
+ struct SERVER_INFO_1555 i1555;
+ struct SERVER_INFO_1556 i1556;
+ struct SERVER_INFO_1557 i1557;
+ struct SERVER_INFO_1560 i1560;
+ struct SERVER_INFO_1561 i1561;
+ struct SERVER_INFO_1562 i1562;
+ struct SERVER_INFO_1563 i1563;
+ struct SERVER_INFO_1564 i1564;
+ struct SERVER_INFO_1565 i1565;
+ struct SERVER_INFO_1566 i1566;
+ struct SERVER_INFO_1567 i1567;
+ struct SERVER_INFO_1568 i1568;
+ struct SERVER_INFO_1569 i1569;
+ struct SERVER_INFO_1570 i1570;
+ struct SERVER_INFO_1571 i1571;
+ struct SERVER_INFO_1572 i1572;
+ struct SERVER_INFO_1573 i1573;
+ struct SERVER_INFO_1574 i1574;
+ struct SERVER_INFO_1575 i1575;
+ struct SERVER_INFO_1576 i1576;
+ struct SERVER_INFO_1577 i1577;
+ struct SERVER_INFO_1578 i1578;
+ struct SERVER_INFO_1579 i1579;
+ struct SERVER_INFO_1580 i1580;
+ struct SERVER_INFO_1581 i1581;
+ struct SERVER_INFO_1582 i1582;
+ struct SERVER_INFO_1583 i1583;
+ struct SERVER_INFO_1584 i1584;
+ struct SERVER_INFO_1585 i1585;
+ struct SERVER_INFO_1586 i1586;
+ struct SERVER_INFO_1587 i1587;
+ struct SERVER_INFO_1588 i1588;
+ struct SERVER_INFO_1590 i1590;
+ struct SERVER_INFO_1591 i1591;
+ struct SERVER_INFO_1592 i1592;
+ struct SERVER_INFO_1593 i1593;
+ struct SERVER_INFO_1594 i1594;
+ struct SERVER_INFO_1595 i1595;
+ struct SERVER_INFO_1596 i1596;
+ struct SERVER_INFO_1597 i1597;
+ struct SERVER_INFO_1598 i1598;
+ struct SERVER_INFO_1599 i1599;
+ struct SERVER_INFO_1600 i1600;
+ struct SERVER_INFO_1601 i1601;
+ struct SERVER_INFO_1602 i1602;
+#endif
+ uint32_t num_info = 0;
+
+ switch (level) {
+ case 100:
+ i100.sv100_platform_id = i->info100->platform_id;
+ i100.sv100_name = talloc_strdup(mem_ctx, i->info100->server_name);
+
+ ADD_TO_ARRAY(mem_ctx, struct SERVER_INFO_100, i100,
+ (struct SERVER_INFO_100 **)buffer,
+ &num_info);
+ break;
+
+ case 101:
+ i101.sv101_platform_id = i->info101->platform_id;
+ i101.sv101_name = talloc_strdup(mem_ctx, i->info101->server_name);
+ i101.sv101_version_major = i->info101->version_major;
+ i101.sv101_version_minor = i->info101->version_minor;
+ i101.sv101_type = i->info101->server_type;
+ i101.sv101_comment = talloc_strdup(mem_ctx, i->info101->comment);
+
+ ADD_TO_ARRAY(mem_ctx, struct SERVER_INFO_101, i101,
+ (struct SERVER_INFO_101 **)buffer,
+ &num_info);
+ break;
+
+ case 102:
+ i102.sv102_platform_id = i->info102->platform_id;
+ i102.sv102_name = talloc_strdup(mem_ctx, i->info102->server_name);
+ i102.sv102_version_major = i->info102->version_major;
+ i102.sv102_version_minor = i->info102->version_minor;
+ i102.sv102_type = i->info102->server_type;
+ i102.sv102_comment = talloc_strdup(mem_ctx, i->info102->comment);
+ i102.sv102_users = i->info102->users;
+ i102.sv102_disc = i->info102->disc;
+ i102.sv102_hidden = i->info102->hidden;
+ i102.sv102_announce = i->info102->announce;
+ i102.sv102_anndelta = i->info102->anndelta;
+ i102.sv102_licenses = i->info102->licenses;
+ i102.sv102_userpath = talloc_strdup(mem_ctx, i->info102->userpath);
+
+ ADD_TO_ARRAY(mem_ctx, struct SERVER_INFO_102, i102,
+ (struct SERVER_INFO_102 **)buffer,
+ &num_info);
+ break;
+
+ case 402:
+
+ i402.sv402_ulist_mtime = i->info402->ulist_mtime;
+ i402.sv402_glist_mtime = i->info402->glist_mtime;
+ i402.sv402_alist_mtime = i->info402->alist_mtime;
+ i402.sv402_alerts = talloc_strdup(mem_ctx, i->info402->alerts);
+ i402.sv402_security = i->info402->security;
+ i402.sv402_numadmin = i->info402->numadmin;
+ i402.sv402_lanmask = i->info402->lanmask;
+ i402.sv402_guestacct = talloc_strdup(mem_ctx, i->info402->guestaccount);
+ i402.sv402_chdevs = i->info402->chdevs;
+ i402.sv402_chdevq = i->info402->chdevqs;
+ i402.sv402_chdevjobs = i->info402->chdevjobs;
+ i402.sv402_connections = i->info402->connections;
+ i402.sv402_shares = i->info402->shares;
+ i402.sv402_openfiles = i->info402->openfiles;
+ i402.sv402_sessopens = i->info402->sessopen;
+ i402.sv402_sessvcs = i->info402->sesssvc;
+ i402.sv402_sessreqs = i->info402->sessreqs;
+ i402.sv402_opensearch = i->info402->opensearch;
+ i402.sv402_activelocks = i->info402->activelocks;
+ i402.sv402_numreqbuf = i->info402->numreqbufs;
+ i402.sv402_sizreqbuf = i->info402->sizereqbufs;
+ i402.sv402_numbigbuf = i->info402->numbigbufs;
+ i402.sv402_numfiletasks = i->info402->numfiletasks;
+ i402.sv402_alertsched = i->info402->alertsched;
+ i402.sv402_erroralert = i->info402->erroralert;
+ i402.sv402_logonalert = i->info402->logonalert;
+ i402.sv402_accessalert = i->info402->accessalert;
+ i402.sv402_diskalert = i->info402->diskalert;
+ i402.sv402_netioalert = i->info402->netioalert;
+ i402.sv402_maxauditsz = i->info402->maxaudits;
+ i402.sv402_srvheuristics = i->info402->srvheuristics;
+
+ ADD_TO_ARRAY(mem_ctx, struct SERVER_INFO_402, i402,
+ (struct SERVER_INFO_402 **)buffer,
+ &num_info);
+ break;
+
+ case 403:
+
+ i403.sv403_ulist_mtime = i->info403->ulist_mtime;
+ i403.sv403_glist_mtime = i->info403->glist_mtime;
+ i403.sv403_alist_mtime = i->info403->alist_mtime;
+ i403.sv403_alerts = talloc_strdup(mem_ctx, i->info403->alerts);
+ i403.sv403_security = i->info403->security;
+ i403.sv403_numadmin = i->info403->numadmin;
+ i403.sv403_lanmask = i->info403->lanmask;
+ i403.sv403_guestacct = talloc_strdup(mem_ctx, i->info403->guestaccount);
+ i403.sv403_chdevs = i->info403->chdevs;
+ i403.sv403_chdevq = i->info403->chdevqs;
+ i403.sv403_chdevjobs = i->info403->chdevjobs;
+ i403.sv403_connections = i->info403->connections;
+ i403.sv403_shares = i->info403->shares;
+ i403.sv403_openfiles = i->info403->openfiles;
+ i403.sv403_sessopens = i->info403->sessopen;
+ i403.sv403_sessvcs = i->info403->sesssvc;
+ i403.sv403_sessreqs = i->info403->sessreqs;
+ i403.sv403_opensearch = i->info403->opensearch;
+ i403.sv403_activelocks = i->info403->activelocks;
+ i403.sv403_numreqbuf = i->info403->numreqbufs;
+ i403.sv403_sizreqbuf = i->info403->sizereqbufs;
+ i403.sv403_numbigbuf = i->info403->numbigbufs;
+ i403.sv403_numfiletasks = i->info403->numfiletasks;
+ i403.sv403_alertsched = i->info403->alertsched;
+ i403.sv403_erroralert = i->info403->erroralert;
+ i403.sv403_logonalert = i->info403->logonalert;
+ i403.sv403_accessalert = i->info403->accessalert;
+ i403.sv403_diskalert = i->info403->diskalert;
+ i403.sv403_netioalert = i->info403->netioalert;
+ i403.sv403_maxauditsz = i->info403->maxaudits;
+ i403.sv403_srvheuristics = i->info403->srvheuristics;
+ i403.sv403_auditedevents = i->info403->auditedevents;
+ i403.sv403_autoprofile = i->info403->auditprofile;
+ i403.sv403_autopath = talloc_strdup(mem_ctx, i->info403->autopath);
+
+ ADD_TO_ARRAY(mem_ctx, struct SERVER_INFO_403, i403,
+ (struct SERVER_INFO_403 **)buffer,
+ &num_info);
+ break;
+
+ case 502:
+ i502.sv502_sessopens = i->info502->sessopen;
+ i502.sv502_sessvcs = i->info502->sesssvc;
+ i502.sv502_opensearch = i->info502->opensearch;
+ i502.sv502_sizreqbuf = i->info502->sizereqbufs;
+ i502.sv502_initworkitems = i->info502->initworkitems;
+ i502.sv502_maxworkitems = i->info502->maxworkitems;
+ i502.sv502_rawworkitems = i->info502->rawworkitems;
+ i502.sv502_irpstacksize = i->info502->irpstacksize;
+ i502.sv502_maxrawbuflen = i->info502->maxrawbuflen;
+ i502.sv502_sessusers = i->info502->sessusers;
+ i502.sv502_sessconns = i->info502->sessconns;
+ i502.sv502_maxpagedmemoryusage = i->info502->maxpagedmemoryusage;
+ i502.sv502_maxnonpagedmemoryusage = i->info502->maxnonpagedmemoryusage;
+ i502.sv502_enablesoftcompat = i->info502->enablesoftcompat;
+ i502.sv502_enableforcedlogoff = i->info502->enableforcedlogoff;
+ i502.sv502_timesource = i->info502->timesource;
+ i502.sv502_acceptdownlevelapis = i->info502->acceptdownlevelapis;
+ i502.sv502_lmannounce = i->info502->lmannounce;
+
+ ADD_TO_ARRAY(mem_ctx, struct SERVER_INFO_502, i502,
+ (struct SERVER_INFO_502 **)buffer,
+ &num_info);
+ break;
+
+ case 503:
+ i503.sv503_sessopens = i->info503->sessopen;
+ i503.sv503_sessvcs = i->info503->sesssvc;
+ i503.sv503_opensearch = i->info503->opensearch;
+ i503.sv503_sizreqbuf = i->info503->sizereqbufs;
+ i503.sv503_initworkitems = i->info503->initworkitems;
+ i503.sv503_maxworkitems = i->info503->maxworkitems;
+ i503.sv503_rawworkitems = i->info503->rawworkitems;
+ i503.sv503_irpstacksize = i->info503->irpstacksize;
+ i503.sv503_maxrawbuflen = i->info503->maxrawbuflen;
+ i503.sv503_sessusers = i->info503->sessusers;
+ i503.sv503_sessconns = i->info503->sessconns;
+ i503.sv503_maxpagedmemoryusage = i->info503->maxpagedmemoryusage;
+ i503.sv503_maxnonpagedmemoryusage = i->info503->maxnonpagedmemoryusage;
+ i503.sv503_enablesoftcompat = i->info503->enablesoftcompat;
+ i503.sv503_enableforcedlogoff = i->info503->enableforcedlogoff;
+ i503.sv503_timesource = i->info503->timesource;
+ i503.sv503_acceptdownlevelapis = i->info503->acceptdownlevelapis;
+ i503.sv503_lmannounce = i->info503->lmannounce;
+ i503.sv503_domain = talloc_strdup(mem_ctx, i->info503->domain);
+ i503.sv503_maxcopyreadlen = i->info503->maxcopyreadlen;
+ i503.sv503_maxcopywritelen = i->info503->maxcopywritelen;
+ i503.sv503_minkeepsearch = i->info503->minkeepsearch;
+ i503.sv503_maxkeepsearch = i->info503->maxkeepsearch;
+ i503.sv503_minkeepcomplsearch = i->info503->minkeepcomplsearch;
+ i503.sv503_maxkeepcomplsearch = i->info503->maxkeepcomplsearch;
+ i503.sv503_threadcountadd = i->info503->threadcountadd;
+ i503.sv503_numblockthreads = i->info503->numlockthreads;
+ i503.sv503_scavtimeout = i->info503->scavtimeout;
+ i503.sv503_minrcvqueue = i->info503->minrcvqueue;
+ i503.sv503_minfreeworkitems = i->info503->minfreeworkitems;
+ i503.sv503_xactmemsize = i->info503->xactmemsize;
+ i503.sv503_threadpriority = i->info503->threadpriority;
+ i503.sv503_maxmpxct = i->info503->maxmpxct;
+ i503.sv503_oplockbreakwait = i->info503->oplockbreakwait;
+ i503.sv503_oplockbreakresponsewait = i->info503->oplockbreakresponsewait;
+ i503.sv503_enableoplocks = i->info503->enableoplocks;
+ i503.sv503_enableoplockforceclose = i->info503->enableoplockforceclose;
+ i503.sv503_enablefcbopens = i->info503->enablefcbopens;
+ i503.sv503_enableraw = i->info503->enableraw;
+ i503.sv503_enablesharednetdrives = i->info503->enablesharednetdrives;
+ i503.sv503_minfreeconnections = i->info503->minfreeconnections;
+ i503.sv503_maxfreeconnections = i->info503->maxfreeconnections;
+
+ ADD_TO_ARRAY(mem_ctx, struct SERVER_INFO_503, i503,
+ (struct SERVER_INFO_503 **)buffer,
+ &num_info);
+ break;
+
+ case 599:
+ i599.sv599_sessopens = i->info599->sessopen;
+ i599.sv599_sessvcs = i->info599->sesssvc;
+ i599.sv599_opensearch = i->info599->opensearch;
+ i599.sv599_sizreqbuf = i->info599->sizereqbufs;
+ i599.sv599_initworkitems = i->info599->initworkitems;
+ i599.sv599_maxworkitems = i->info599->maxworkitems;
+ i599.sv599_rawworkitems = i->info599->rawworkitems;
+ i599.sv599_irpstacksize = i->info599->irpstacksize;
+ i599.sv599_maxrawbuflen = i->info599->maxrawbuflen;
+ i599.sv599_sessusers = i->info599->sessusers;
+ i599.sv599_sessconns = i->info599->sessconns;
+ i599.sv599_maxpagedmemoryusage = i->info599->maxpagedmemoryusage;
+ i599.sv599_maxnonpagedmemoryusage = i->info599->maxnonpagedmemoryusage;
+ i599.sv599_enablesoftcompat = i->info599->enablesoftcompat;
+ i599.sv599_enableforcedlogoff = i->info599->enableforcedlogoff;
+ i599.sv599_timesource = i->info599->timesource;
+ i599.sv599_acceptdownlevelapis = i->info599->acceptdownlevelapis;
+ i599.sv599_lmannounce = i->info599->lmannounce;
+ i599.sv599_domain = talloc_strdup(mem_ctx, i->info599->domain);
+ i599.sv599_maxcopyreadlen = i->info599->maxcopyreadlen;
+ i599.sv599_maxcopywritelen = i->info599->maxcopywritelen;
+ i599.sv599_minkeepsearch = i->info599->minkeepsearch;
+ i599.sv599_maxkeepsearch = 0; /* ?? */
+ i599.sv599_minkeepcomplsearch = i->info599->minkeepcomplsearch;
+ i599.sv599_maxkeepcomplsearch = i->info599->maxkeepcomplsearch;
+ i599.sv599_threadcountadd = i->info599->threadcountadd;
+ i599.sv599_numblockthreads = i->info599->numlockthreads; /* typo ? */
+ i599.sv599_scavtimeout = i->info599->scavtimeout;
+ i599.sv599_minrcvqueue = i->info599->minrcvqueue;
+ i599.sv599_minfreeworkitems = i->info599->minfreeworkitems;
+ i599.sv599_xactmemsize = i->info599->xactmemsize;
+ i599.sv599_threadpriority = i->info599->threadpriority;
+ i599.sv599_maxmpxct = i->info599->maxmpxct;
+ i599.sv599_oplockbreakwait = i->info599->oplockbreakwait;
+ i599.sv599_oplockbreakresponsewait = i->info599->oplockbreakresponsewait;
+ i599.sv599_enableoplocks = i->info599->enableoplocks;
+ i599.sv599_enableoplockforceclose = i->info599->enableoplockforceclose;
+ i599.sv599_enablefcbopens = i->info599->enablefcbopens;
+ i599.sv599_enableraw = i->info599->enableraw;
+ i599.sv599_enablesharednetdrives = i->info599->enablesharednetdrives;
+ i599.sv599_minfreeconnections = i->info599->minfreeconnections;
+ i599.sv599_maxfreeconnections = i->info599->maxfreeconnections;
+ i599.sv599_initsesstable = i->info599->initsesstable;
+ i599.sv599_initconntable = i->info599->initconntable;
+ i599.sv599_initfiletable = i->info599->initfiletable;
+ i599.sv599_initsearchtable = i->info599->initsearchtable;
+ i599.sv599_alertschedule = i->info599->alertsched;
+ i599.sv599_errorthreshold = i->info599->errortreshold;
+ i599.sv599_networkerrorthreshold = i->info599->networkerrortreshold;
+ i599.sv599_diskspacethreshold = i->info599->diskspacetreshold;
+ i599.sv599_reserved = i->info599->reserved;
+ i599.sv599_maxlinkdelay = i->info599->maxlinkdelay;
+ i599.sv599_minlinkthroughput = i->info599->minlinkthroughput;
+ i599.sv599_linkinfovalidtime = i->info599->linkinfovalidtime;
+ i599.sv599_scavqosinfoupdatetime = i->info599->scavqosinfoupdatetime;
+ i599.sv599_maxworkitemidletime = i->info599->maxworkitemidletime;
+
+ ADD_TO_ARRAY(mem_ctx, struct SERVER_INFO_599, i599,
+ (struct SERVER_INFO_599 **)buffer,
+ &num_info);
+ break;
+
+ case 1005:
+ i1005.sv1005_comment = talloc_strdup(mem_ctx, i->info1005->comment);
+
+ ADD_TO_ARRAY(mem_ctx, struct SERVER_INFO_1005, i1005,
+ (struct SERVER_INFO_1005 **)buffer,
+ &num_info);
+ break;
+ default:
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetServerGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetServerGetInfo *r)
+{
+ NTSTATUS status;
+ WERROR werr;
+ union srvsvc_NetSrvInfo info;
+ struct dcerpc_binding_handle *b;
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 100:
+ case 101:
+ case 102:
+ case 402:
+ case 502:
+ case 503:
+ case 1005:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_srvsvc,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_srvsvc_NetSrvGetInfo(b, talloc_tos(),
+ r->in.server_name,
+ r->in.level,
+ &info,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = map_server_info_to_SERVER_INFO_buffer(ctx, r->in.level, &info,
+ r->out.buffer);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR NetServerSetInfo_l_1005(struct libnetapi_ctx *ctx,
+ struct NetServerSetInfo *r)
+{
+ WERROR werr = WERR_OK;
+ sbcErr err;
+ struct smbconf_ctx *conf_ctx;
+ struct srvsvc_NetSrvInfo1005 *info1005;
+
+ if (!r->in.buffer) {
+ *r->out.parm_error = 1005; /* sure here ? */
+ return WERR_INVALID_PARAMETER;
+ }
+
+ info1005 = (struct srvsvc_NetSrvInfo1005 *)r->in.buffer;
+
+ if (!info1005->comment) {
+ *r->out.parm_error = 1005;
+ return WERR_INVALID_PARAMETER;
+ }
+
+ if (!lp_config_backend_is_registry()) {
+ libnetapi_set_error_string(ctx,
+ "Configuration manipulation requested but not "
+ "supported by backend");
+ return WERR_NOT_SUPPORTED;
+ }
+
+ err = smbconf_init_reg(ctx, &conf_ctx, NULL);
+ if (!SBC_ERROR_IS_OK(err)) {
+ libnetapi_set_error_string(ctx,
+ "Could not initialize backend: %s",
+ sbcErrorString(err));
+ werr = WERR_SERVICE_DOES_NOT_EXIST;
+ goto done;
+ }
+
+ err = smbconf_set_global_parameter(conf_ctx, "server string",
+ info1005->comment);
+ if (!SBC_ERROR_IS_OK(err)) {
+ libnetapi_set_error_string(ctx,
+ "Could not set global parameter: %s",
+ sbcErrorString(err));
+ werr = WERR_SERVICE_DOES_NOT_EXIST;
+ goto done;
+ }
+
+ done:
+ smbconf_shutdown(conf_ctx);
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetServerSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetServerSetInfo *r)
+{
+ switch (r->in.level) {
+ case 1005:
+ return NetServerSetInfo_l_1005(ctx, r);
+ default:
+ break;
+ }
+
+ return WERR_INVALID_LEVEL;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetServerSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetServerSetInfo *r)
+{
+ NTSTATUS status;
+ WERROR werr;
+ union srvsvc_NetSrvInfo info;
+ struct dcerpc_binding_handle *b;
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_srvsvc,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ switch (r->in.level) {
+ case 1005:
+ info.info1005 = (struct srvsvc_NetSrvInfo1005 *)r->in.buffer;
+ break;
+ default:
+ werr = WERR_NOT_SUPPORTED;
+ goto done;
+ }
+
+ status = dcerpc_srvsvc_NetSrvSetInfo(b, talloc_tos(),
+ r->in.server_name,
+ r->in.level,
+ &info,
+ r->out.parm_error,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetRemoteTOD_r(struct libnetapi_ctx *ctx,
+ struct NetRemoteTOD *r)
+{
+ NTSTATUS status;
+ WERROR werr;
+ struct srvsvc_NetRemoteTODInfo *info = NULL;
+ struct dcerpc_binding_handle *b;
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_srvsvc,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_srvsvc_NetRemoteTOD(b, talloc_tos(),
+ r->in.server_name,
+ &info,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ *r->out.buffer = (uint8_t *)talloc_memdup(ctx, info,
+ sizeof(struct srvsvc_NetRemoteTODInfo));
+ W_ERROR_HAVE_NO_MEMORY(*r->out.buffer);
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetRemoteTOD_l(struct libnetapi_ctx *ctx,
+ struct NetRemoteTOD *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRemoteTOD);
+}
+
diff --git a/source3/lib/netapi/share.c b/source3/lib/netapi/share.c
new file mode 100644
index 0000000..7f142fc
--- /dev/null
+++ b/source3/lib/netapi/share.c
@@ -0,0 +1,573 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Share Support
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+#include "../librpc/gen_ndr/ndr_srvsvc_c.h"
+#include "librpc/gen_ndr/ndr_security.h"
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS map_srvsvc_share_info_to_SHARE_INFO_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ union srvsvc_NetShareInfo *info,
+ uint8_t **buffer,
+ uint32_t *num_shares)
+{
+ struct SHARE_INFO_0 i0;
+ struct SHARE_INFO_1 i1;
+ struct SHARE_INFO_2 i2;
+ struct SHARE_INFO_501 i501;
+ struct SHARE_INFO_1005 i1005;
+
+ struct srvsvc_NetShareInfo0 *s0;
+ struct srvsvc_NetShareInfo1 *s1;
+ struct srvsvc_NetShareInfo2 *s2;
+ struct srvsvc_NetShareInfo501 *s501;
+ struct srvsvc_NetShareInfo1005 *s1005;
+
+ if (!buffer) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ switch (level) {
+ case 0:
+ s0 = info->info0;
+
+ i0.shi0_netname = talloc_strdup(mem_ctx, s0->name);
+
+ ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_0, i0,
+ (struct SHARE_INFO_0 **)buffer,
+ num_shares);
+ break;
+
+ case 1:
+ s1 = info->info1;
+
+ i1.shi1_netname = talloc_strdup(mem_ctx, s1->name);
+ i1.shi1_type = s1->type;
+ i1.shi1_remark = talloc_strdup(mem_ctx, s1->comment);
+
+ ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_1, i1,
+ (struct SHARE_INFO_1 **)buffer,
+ num_shares);
+ break;
+
+ case 2:
+ s2 = info->info2;
+
+ i2.shi2_netname = talloc_strdup(mem_ctx, s2->name);
+ i2.shi2_type = s2->type;
+ i2.shi2_remark = talloc_strdup(mem_ctx, s2->comment);
+ i2.shi2_permissions = s2->permissions;
+ i2.shi2_max_uses = s2->max_users;
+ i2.shi2_current_uses = s2->current_users;
+ i2.shi2_path = talloc_strdup(mem_ctx, s2->path);
+ i2.shi2_passwd = talloc_strdup(mem_ctx, s2->password);
+
+ ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_2, i2,
+ (struct SHARE_INFO_2 **)buffer,
+ num_shares);
+ break;
+
+ case 501:
+ s501 = info->info501;
+
+ i501.shi501_netname = talloc_strdup(mem_ctx, s501->name);
+ i501.shi501_type = s501->type;
+ i501.shi501_remark = talloc_strdup(mem_ctx, s501->comment);
+ i501.shi501_flags = s501->csc_policy;
+
+ ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_501, i501,
+ (struct SHARE_INFO_501 **)buffer,
+ num_shares);
+ break;
+
+ case 1005:
+ s1005 = info->info1005;
+
+ i1005.shi1005_flags = s1005->dfs_flags;
+
+ ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_1005, i1005,
+ (struct SHARE_INFO_1005 **)buffer,
+ num_shares);
+ break;
+
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS map_SHARE_INFO_buffer_to_srvsvc_share_info(TALLOC_CTX *mem_ctx,
+ uint8_t *buffer,
+ uint32_t level,
+ union srvsvc_NetShareInfo *info)
+{
+ struct SHARE_INFO_2 *i2 = NULL;
+ struct SHARE_INFO_502 *i502 = NULL;
+ struct SHARE_INFO_1004 *i1004 = NULL;
+ struct srvsvc_NetShareInfo2 *s2 = NULL;
+ struct srvsvc_NetShareInfo502 *s502 = NULL;
+ struct srvsvc_NetShareInfo1004 *s1004 = NULL;
+
+ if (!buffer) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ switch (level) {
+ case 2:
+ i2 = (struct SHARE_INFO_2 *)buffer;
+
+ s2 = talloc(mem_ctx, struct srvsvc_NetShareInfo2);
+ NT_STATUS_HAVE_NO_MEMORY(s2);
+
+ s2->name = i2->shi2_netname;
+ s2->type = i2->shi2_type;
+ s2->comment = i2->shi2_remark;
+ s2->permissions = i2->shi2_permissions;
+ s2->max_users = i2->shi2_max_uses;
+ s2->current_users = i2->shi2_current_uses;
+ s2->path = i2->shi2_path;
+ s2->password = i2->shi2_passwd;
+
+ info->info2 = s2;
+
+ break;
+
+ case 502:
+ i502 = (struct SHARE_INFO_502 *)buffer;
+
+ s502 = talloc(mem_ctx, struct srvsvc_NetShareInfo502);
+ NT_STATUS_HAVE_NO_MEMORY(s502);
+
+ s502->name = i502->shi502_netname;
+ s502->type = i502->shi502_type;
+ s502->comment = i502->shi502_remark;
+ s502->permissions = i502->shi502_permissions;
+ s502->max_users = i502->shi502_max_uses;
+ s502->current_users = i502->shi502_current_uses;
+ s502->path = i502->shi502_path;
+ s502->password = i502->shi502_passwd;
+ s502->sd_buf.sd_size =
+ ndr_size_security_descriptor(i502->shi502_security_descriptor, 0);
+ s502->sd_buf.sd = i502->shi502_security_descriptor;
+
+ info->info502 = s502;
+
+ break;
+
+ case 1004:
+ i1004 = (struct SHARE_INFO_1004 *)buffer;
+
+ s1004 = talloc(mem_ctx, struct srvsvc_NetShareInfo1004);
+ NT_STATUS_HAVE_NO_MEMORY(s1004);
+
+ s1004->comment = i1004->shi1004_remark;
+
+ info->info1004 = s1004;
+
+ break;
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareAdd_r(struct libnetapi_ctx *ctx,
+ struct NetShareAdd *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ union srvsvc_NetShareInfo info;
+ struct dcerpc_binding_handle *b;
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 2:
+ case 502:
+ break;
+ case 503:
+ return WERR_NOT_SUPPORTED;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_srvsvc,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = map_SHARE_INFO_buffer_to_srvsvc_share_info(ctx,
+ r->in.buffer,
+ r->in.level,
+ &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = dcerpc_srvsvc_NetShareAdd(b, talloc_tos(),
+ r->in.server_name,
+ r->in.level,
+ &info,
+ r->out.parm_err,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareAdd_l(struct libnetapi_ctx *ctx,
+ struct NetShareAdd *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareAdd);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareDel_r(struct libnetapi_ctx *ctx,
+ struct NetShareDel *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct dcerpc_binding_handle *b;
+
+ if (!r->in.net_name) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_srvsvc,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_srvsvc_NetShareDel(b, talloc_tos(),
+ r->in.server_name,
+ r->in.net_name,
+ r->in.reserved,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareDel_l(struct libnetapi_ctx *ctx,
+ struct NetShareDel *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareDel);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareEnum_r(struct libnetapi_ctx *ctx,
+ struct NetShareEnum *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct srvsvc_NetShareInfoCtr info_ctr;
+ struct srvsvc_NetShareCtr0 ctr0;
+ struct srvsvc_NetShareCtr1 ctr1;
+ struct srvsvc_NetShareCtr2 ctr2;
+ uint32_t i;
+ struct dcerpc_binding_handle *b;
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ case 2:
+ break;
+ case 502:
+ case 503:
+ return WERR_NOT_SUPPORTED;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ ZERO_STRUCT(info_ctr);
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_srvsvc,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ info_ctr.level = r->in.level;
+ switch (r->in.level) {
+ case 0:
+ ZERO_STRUCT(ctr0);
+ info_ctr.ctr.ctr0 = &ctr0;
+ break;
+ case 1:
+ ZERO_STRUCT(ctr1);
+ info_ctr.ctr.ctr1 = &ctr1;
+ break;
+ case 2:
+ ZERO_STRUCT(ctr2);
+ info_ctr.ctr.ctr2 = &ctr2;
+ break;
+ }
+
+ status = dcerpc_srvsvc_NetShareEnumAll(b, talloc_tos(),
+ r->in.server_name,
+ &info_ctr,
+ r->in.prefmaxlen,
+ r->out.total_entries,
+ r->out.resume_handle,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!W_ERROR_IS_OK(werr) && !W_ERROR_EQUAL(werr, WERR_MORE_DATA)) {
+ goto done;
+ }
+
+ for (i=0; i < info_ctr.ctr.ctr1->count; i++) {
+ union srvsvc_NetShareInfo _i = {0};
+ switch (r->in.level) {
+ case 0:
+ _i.info0 = &info_ctr.ctr.ctr0->array[i];
+ break;
+ case 1:
+ _i.info1 = &info_ctr.ctr.ctr1->array[i];
+ break;
+ case 2:
+ _i.info2 = &info_ctr.ctr.ctr2->array[i];
+ break;
+ }
+
+ status = map_srvsvc_share_info_to_SHARE_INFO_buffer(ctx,
+ r->in.level,
+ &_i,
+ r->out.buffer,
+ r->out.entries_read);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareEnum_l(struct libnetapi_ctx *ctx,
+ struct NetShareEnum *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareEnum);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetShareGetInfo *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ union srvsvc_NetShareInfo info;
+ uint32_t num_entries = 0;
+ struct dcerpc_binding_handle *b;
+
+ if (!r->in.net_name || !r->out.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ case 2:
+ case 501:
+ case 1005:
+ break;
+ case 502:
+ case 503:
+ return WERR_NOT_SUPPORTED;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_srvsvc,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_srvsvc_NetShareGetInfo(b, talloc_tos(),
+ r->in.server_name,
+ r->in.net_name,
+ r->in.level,
+ &info,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = map_srvsvc_share_info_to_SHARE_INFO_buffer(ctx,
+ r->in.level,
+ &info,
+ r->out.buffer,
+ &num_entries);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetShareGetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareGetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetShareSetInfo *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ union srvsvc_NetShareInfo info;
+ struct dcerpc_binding_handle *b;
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 2:
+ case 1004:
+ break;
+ case 1:
+ case 502:
+ case 503:
+ case 1005:
+ case 1006:
+ case 1501:
+ return WERR_NOT_SUPPORTED;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_srvsvc,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = map_SHARE_INFO_buffer_to_srvsvc_share_info(ctx,
+ r->in.buffer,
+ r->in.level,
+ &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = dcerpc_srvsvc_NetShareSetInfo(b, talloc_tos(),
+ r->in.server_name,
+ r->in.net_name,
+ r->in.level,
+ &info,
+ r->out.parm_err,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetShareSetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareSetInfo);
+}
diff --git a/source3/lib/netapi/shutdown.c b/source3/lib/netapi/shutdown.c
new file mode 100644
index 0000000..9e1e8e1
--- /dev/null
+++ b/source3/lib/netapi/shutdown.c
@@ -0,0 +1,110 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Shutdown Support
+ * Copyright (C) Guenther Deschner 2009
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+#include "../librpc/gen_ndr/ndr_initshutdown_c.h"
+#include "rpc_client/init_lsa.h"
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShutdownInit_r(struct libnetapi_ctx *ctx,
+ struct NetShutdownInit *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct lsa_StringLarge message;
+ struct dcerpc_binding_handle *b;
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_initshutdown,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_StringLarge(&message, r->in.message);
+
+ status = dcerpc_initshutdown_Init(b, talloc_tos(),
+ NULL,
+ &message,
+ r->in.timeout,
+ r->in.force_apps,
+ r->in.do_reboot,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShutdownInit_l(struct libnetapi_ctx *ctx,
+ struct NetShutdownInit *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShutdownInit);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShutdownAbort_r(struct libnetapi_ctx *ctx,
+ struct NetShutdownAbort *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct dcerpc_binding_handle *b;
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_initshutdown,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_initshutdown_Abort(b, talloc_tos(),
+ NULL,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShutdownAbort_l(struct libnetapi_ctx *ctx,
+ struct NetShutdownAbort *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShutdownAbort);
+}
diff --git a/source3/lib/netapi/sid.c b/source3/lib/netapi/sid.c
new file mode 100644
index 0000000..ba22374
--- /dev/null
+++ b/source3/lib/netapi/sid.c
@@ -0,0 +1,71 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Support
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "lib/netapi/netapi.h"
+#include "../libcli/security/security.h"
+
+/****************************************************************
+****************************************************************/
+
+int ConvertSidToStringSid(const struct domsid *sid,
+ char **sid_string)
+{
+ struct dom_sid_buf buf;
+
+ if (!sid || !sid_string) {
+ return false;
+ }
+
+ *sid_string = SMB_STRDUP(
+ dom_sid_str_buf((const struct dom_sid *)sid, &buf));
+
+ if (!*sid_string) {
+ return false;
+ }
+
+ return true;
+}
+
+/****************************************************************
+****************************************************************/
+
+int ConvertStringSidToSid(const char *sid_string,
+ struct domsid **sid)
+{
+ struct dom_sid _sid;
+
+ if (!sid_string || !sid) {
+ return false;
+ }
+
+ if (!string_to_sid(&_sid, sid_string)) {
+ return false;
+ }
+
+ *sid = (struct domsid *)SMB_MALLOC(sizeof(struct domsid));
+ if (!*sid) {
+ return false;
+ }
+
+ sid_copy((struct dom_sid*)*sid, &_sid);
+
+ return true;
+}
diff --git a/source3/lib/netapi/tests/common.c b/source3/lib/netapi/tests/common.c
new file mode 100644
index 0000000..a01a870
--- /dev/null
+++ b/source3/lib/netapi/tests/common.c
@@ -0,0 +1,116 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi testsuite
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include <popt.h>
+#include <netapi.h>
+
+#include "common.h"
+
+void popt_common_callback(poptContext con,
+ enum poptCallbackReason reason,
+ const struct poptOption *opt,
+ const char *arg, const void *data)
+{
+ struct libnetapi_ctx *ctx = NULL;
+
+ libnetapi_getctx(&ctx);
+
+ if (reason == POPT_CALLBACK_REASON_PRE) {
+ }
+
+ if (reason == POPT_CALLBACK_REASON_POST) {
+ }
+
+ if (!opt) {
+ return;
+ }
+ switch (opt->val) {
+ case 'U': {
+ char *puser = strdup(arg);
+ char *p = NULL;
+
+ if ((p = strchr(puser,'%'))) {
+ size_t len;
+ *p = 0;
+ libnetapi_set_username(ctx, puser);
+ libnetapi_set_password(ctx, p+1);
+ len = strlen(p+1);
+ memset(strchr(arg,'%')+1,'X',len);
+ } else {
+ libnetapi_set_username(ctx, puser);
+ }
+ free(puser);
+ break;
+ }
+ case 'd':
+ libnetapi_set_debuglevel(ctx, arg);
+ break;
+ case 'p':
+ libnetapi_set_password(ctx, arg);
+ break;
+ case 'k':
+ libnetapi_set_use_kerberos(ctx);
+ break;
+ }
+}
+
+struct poptOption popt_common_netapi_examples[] = {
+ {
+ .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,
+ .arg = (void *)popt_common_callback,
+ },
+ {
+ .longName = "user",
+ .shortName = 'U',
+ .argInfo = POPT_ARG_STRING,
+ .val = 'U',
+ .descrip = "Username used for connection",
+ .argDescrip = "USERNAME",
+ },
+ {
+ .longName = "password",
+ .shortName = 'p',
+ .argInfo = POPT_ARG_STRING,
+ .val = 'p',
+ .descrip = "Password used for connection",
+ .argDescrip = "PASSWORD",
+ },
+ {
+ .longName = "debuglevel",
+ .shortName = 'd',
+ .argInfo = POPT_ARG_STRING,
+ .val = 'd',
+ .descrip = "Debuglevel",
+ .argDescrip = "DEBUGLEVEL",
+ },
+ {
+ .longName = "kerberos",
+ .shortName = 'k',
+ .argInfo = POPT_ARG_NONE,
+ .val = 'k',
+ .descrip = "Use Kerberos",
+ },
+ POPT_TABLEEND
+};
+
diff --git a/source3/lib/netapi/tests/common.h b/source3/lib/netapi/tests/common.h
new file mode 100644
index 0000000..be1a2e4
--- /dev/null
+++ b/source3/lib/netapi/tests/common.h
@@ -0,0 +1,67 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi testsuite
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <popt.h>
+
+void popt_common_callback(poptContext con,
+ enum poptCallbackReason reason,
+ const struct poptOption *opt,
+ const char *arg, const void *data);
+
+extern struct poptOption popt_common_netapi_examples[];
+
+#define POPT_COMMON_LIBNETAPI_EXAMPLES { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_netapi_examples, 0, "Common samba netapi example options:", NULL },
+
+#ifndef POPT_TABLEEND
+#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
+#endif
+
+NET_API_STATUS test_netuseradd(const char *hostname,
+ const char *username);
+
+NET_API_STATUS netapitest_localgroup(struct libnetapi_ctx *ctx,
+ const char *hostname);
+NET_API_STATUS netapitest_user(struct libnetapi_ctx *ctx,
+ const char *hostname);
+NET_API_STATUS netapitest_group(struct libnetapi_ctx *ctx,
+ const char *hostname);
+NET_API_STATUS netapitest_display(struct libnetapi_ctx *ctx,
+ const char *hostname);
+NET_API_STATUS netapitest_share(struct libnetapi_ctx *ctx,
+ const char *hostname);
+NET_API_STATUS netapitest_file(struct libnetapi_ctx *ctx,
+ const char *hostname);
+NET_API_STATUS netapitest_server(struct libnetapi_ctx *ctx,
+ const char *hostname);
+NET_API_STATUS netapitest_wksta(struct libnetapi_ctx *ctx,
+ const char *hostname);
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
+#endif
+
+#define NETAPI_STATUS(x,y,fn) \
+ printf("FAILURE: line %d: %s failed with status: %s (%d)\n", \
+ __LINE__, fn, libnetapi_get_error_string(x,y), y);
+
+#define NETAPI_STATUS_MSG(x,y,fn,z) \
+ printf("FAILURE: line %d: %s failed with status: %s (%d), %s\n", \
+ __LINE__, fn, libnetapi_get_error_string(x,y), y, z);
+
+#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
diff --git a/source3/lib/netapi/tests/netapitest.c b/source3/lib/netapi/tests/netapitest.c
new file mode 100644
index 0000000..fd367bd
--- /dev/null
+++ b/source3/lib/netapi/tests/netapitest.c
@@ -0,0 +1,112 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi testsuite
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status = 0;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("netapitest", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ status = netapitest_localgroup(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ status = netapitest_user(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ status = netapitest_group(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ status = netapitest_display(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ status = netapitest_share(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ status = netapitest_file(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ status = netapitest_server(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ status = netapitest_wksta(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ out:
+ if (status != 0) {
+ printf("testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source3/lib/netapi/tests/netdisplay.c b/source3/lib/netapi/tests/netdisplay.c
new file mode 100644
index 0000000..d7967fa
--- /dev/null
+++ b/source3/lib/netapi/tests/netdisplay.c
@@ -0,0 +1,150 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroup testsuite
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+static NET_API_STATUS test_netquerydisplayinformation(const char *hostname,
+ uint32_t level,
+ const char *name)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ int found_name = 0;
+ const char *current_name;
+ uint8_t *buffer = NULL;
+ uint32_t idx = 0;
+ int i;
+
+ struct NET_DISPLAY_USER *user = NULL;
+ struct NET_DISPLAY_GROUP *group = NULL;
+ struct NET_DISPLAY_MACHINE *machine = NULL;
+
+ printf("testing NetQueryDisplayInformation level %d\n", level);
+
+ do {
+ status = NetQueryDisplayInformation(hostname,
+ level,
+ idx,
+ 1000,
+ (uint32_t)-1,
+ &entries_read,
+ (void **)&buffer);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ switch (level) {
+ case 1:
+ user = (struct NET_DISPLAY_USER *)buffer;
+ break;
+ case 2:
+ machine = (struct NET_DISPLAY_MACHINE *)buffer;
+ break;
+ case 3:
+ group = (struct NET_DISPLAY_GROUP *)buffer;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i=0; i<entries_read; i++) {
+
+ switch (level) {
+ case 1:
+ current_name = user->usri1_name;
+ break;
+ case 2:
+ current_name = machine->usri2_name;
+ break;
+ case 3:
+ current_name = group->grpi3_name;
+ break;
+ default:
+ break;
+ }
+
+ if (name && strcasecmp(current_name, name) == 0) {
+ found_name = 1;
+ }
+
+ switch (level) {
+ case 1:
+ user++;
+ break;
+ case 2:
+ machine++;
+ break;
+ case 3:
+ group++;
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ idx += entries_read;
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ if (name && !found_name) {
+ printf("failed to get name\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+NET_API_STATUS netapitest_display(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status = 0;
+ uint32_t levels[] = { 1, 2, 3};
+ int i;
+
+ printf("NetDisplay tests\n");
+
+ /* test enum */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ status = test_netquerydisplayinformation(hostname, levels[i], NULL);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetQueryDisplayInformation");
+ goto out;
+ }
+ }
+
+ status = 0;
+
+ printf("NetDisplay tests succeeded\n");
+ out:
+ if (status != 0) {
+ printf("NetDisplay testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ return status;
+}
diff --git a/source3/lib/netapi/tests/netfile.c b/source3/lib/netapi/tests/netfile.c
new file mode 100644
index 0000000..bee3c2e
--- /dev/null
+++ b/source3/lib/netapi/tests/netfile.c
@@ -0,0 +1,145 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetFile testsuite
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+static NET_API_STATUS test_netfileenum(const char *hostname,
+ uint32_t level)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ uint8_t *buffer = NULL;
+ int i;
+
+ struct FILE_INFO_2 *i2 = NULL;
+ struct FILE_INFO_3 *i3 = NULL;
+
+ printf("testing NetFileEnum level %d\n", level);
+
+ do {
+ status = NetFileEnum(hostname,
+ NULL,
+ NULL,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ switch (level) {
+ case 2:
+ i2 = (struct FILE_INFO_2 *)buffer;
+ break;
+ case 3:
+ i3 = (struct FILE_INFO_3 *)buffer;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i=0; i<entries_read; i++) {
+
+ switch (level) {
+ case 2:
+ case 3:
+ break;
+ default:
+ break;
+ }
+
+ switch (level) {
+ case 2:
+ i2++;
+ break;
+ case 3:
+ i3++;
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ return 0;
+}
+
+NET_API_STATUS netapitest_file(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status = 0;
+ uint32_t enum_levels[] = { 2, 3 };
+ int i;
+
+ printf("NetFile tests\n");
+
+ /* test enum */
+
+ for (i=0; i<ARRAY_SIZE(enum_levels); i++) {
+
+ status = test_netfileenum(hostname, enum_levels[i]);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetFileEnum");
+ goto out;
+ }
+ }
+
+ /* basic queries */
+#if 0
+ {
+ uint32_t levels[] = { 2, 3 };
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+ uint8_t *buffer = NULL;
+
+ printf("testing NetFileGetInfo level %d\n", levels[i]);
+
+ status = NetFileGetInfo(hostname, fid, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetFileGetInfo");
+ goto out;
+ }
+ }
+ }
+#endif
+
+ status = 0;
+
+ printf("NetFile tests succeeded\n");
+ out:
+ if (status != 0) {
+ printf("NetFile testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ return status;
+}
diff --git a/source3/lib/netapi/tests/netgroup.c b/source3/lib/netapi/tests/netgroup.c
new file mode 100644
index 0000000..dba4fe7
--- /dev/null
+++ b/source3/lib/netapi/tests/netgroup.c
@@ -0,0 +1,503 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroup testsuite
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+static NET_API_STATUS test_netgroupenum(const char *hostname,
+ uint32_t level,
+ const char *groupname)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int found_group = 0;
+ const char *current_name = NULL;
+ uint8_t *buffer = NULL;
+ int i;
+
+ struct GROUP_INFO_0 *info0 = NULL;
+ struct GROUP_INFO_1 *info1 = NULL;
+ struct GROUP_INFO_2 *info2 = NULL;
+ struct GROUP_INFO_3 *info3 = NULL;
+
+ printf("testing NetGroupEnum level %d\n", level);
+
+ do {
+ status = NetGroupEnum(hostname,
+ level,
+ &buffer,
+ 120, /*(uint32_t)-1, */
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ switch (level) {
+ case 0:
+ info0 = (struct GROUP_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct GROUP_INFO_1 *)buffer;
+ break;
+ case 2:
+ info2 = (struct GROUP_INFO_2 *)buffer;
+ break;
+ case 3:
+ info3 = (struct GROUP_INFO_3 *)buffer;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i=0; i<entries_read; i++) {
+
+ switch (level) {
+ case 0:
+ current_name = info0->grpi0_name;
+ break;
+ case 1:
+ current_name = info1->grpi1_name;
+ break;
+ case 2:
+ current_name = info2->grpi2_name;
+ break;
+ case 3:
+ current_name = info3->grpi3_name;
+ break;
+ default:
+ break;
+ }
+
+ if (strcasecmp(current_name, groupname) == 0) {
+ found_group = 1;
+ }
+
+ switch (level) {
+ case 0:
+ info0++;
+ break;
+ case 1:
+ info1++;
+ break;
+ case 2:
+ info2++;
+ break;
+ case 3:
+ info3++;
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ if (!found_group) {
+ printf("failed to get group\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static NET_API_STATUS test_netgroupgetusers(const char *hostname,
+ uint32_t level,
+ const char *groupname,
+ const char *username)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int found_user = 0;
+ const char *current_name = NULL;
+ uint8_t *buffer = NULL;
+ int i;
+
+ struct GROUP_USERS_INFO_0 *info0 = NULL;
+ struct GROUP_USERS_INFO_1 *info1 = NULL;
+
+ printf("testing NetGroupGetUsers level %d\n", level);
+
+ do {
+ status = NetGroupGetUsers(hostname,
+ groupname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+
+ switch (level) {
+ case 0:
+ info0 = (struct GROUP_USERS_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct GROUP_USERS_INFO_1 *)buffer;
+ break;
+ default:
+ break;
+ }
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ current_name = info0->grui0_name;
+ break;
+ case 1:
+ current_name = info1->grui1_name;
+ break;
+ default:
+ break;
+ }
+
+ if (username && strcasecmp(current_name, username) == 0) {
+ found_user = 1;
+ }
+
+ switch (level) {
+ case 0:
+ info0++;
+ break;
+ case 1:
+ info1++;
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ if (username && !found_user) {
+ printf("failed to get user\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static NET_API_STATUS test_netgroupsetusers(const char *hostname,
+ const char *groupname,
+ uint32_t level,
+ size_t num_entries,
+ const char **names)
+{
+ NET_API_STATUS status;
+ uint8_t *buffer = NULL;
+ int i = 0;
+ size_t buf_size = 0;
+
+ struct GROUP_USERS_INFO_0 *g0 = NULL;
+ struct GROUP_USERS_INFO_1 *g1 = NULL;
+
+ printf("testing NetGroupSetUsers level %d\n", level);
+
+ switch (level) {
+ case 0:
+ buf_size = sizeof(struct GROUP_USERS_INFO_0) * num_entries;
+
+ status = NetApiBufferAllocate(buf_size, (void **)&g0);
+ if (status) {
+ goto out;
+ }
+
+ for (i=0; i<num_entries; i++) {
+ g0[i].grui0_name = names[i];
+ }
+
+ buffer = (uint8_t *)g0;
+ break;
+ case 1:
+ buf_size = sizeof(struct GROUP_USERS_INFO_1) * num_entries;
+
+ status = NetApiBufferAllocate(buf_size, (void **)&g1);
+ if (status) {
+ goto out;
+ }
+
+ for (i=0; i<num_entries; i++) {
+ g1[i].grui1_name = names[i];
+ }
+
+ buffer = (uint8_t *)g1;
+ break;
+ default:
+ break;
+ }
+
+ /* NetGroupSetUsers */
+
+ status = NetGroupSetUsers(hostname,
+ groupname,
+ level,
+ buffer,
+ num_entries);
+ if (status) {
+ goto out;
+ }
+
+ out:
+ NetApiBufferFree(buffer);
+ return status;
+}
+
+NET_API_STATUS netapitest_group(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status = 0;
+ const char *username, *groupname, *groupname2;
+ uint8_t *buffer = NULL;
+ struct GROUP_INFO_0 g0;
+ uint32_t parm_err = 0;
+ uint32_t levels[] = { 0, 1, 2, 3};
+ uint32_t enum_levels[] = { 0, 1, 2, 3};
+ uint32_t getmem_levels[] = { 0, 1};
+ int i;
+
+ printf("NetGroup tests\n");
+
+ username = "torture_test_user";
+ groupname = "torture_test_group";
+ groupname2 = "torture_test_group2";
+
+ /* cleanup */
+ NetGroupDel(hostname, groupname);
+ NetGroupDel(hostname, groupname2);
+ NetUserDel(hostname, username);
+
+ /* add a group */
+
+ g0.grpi0_name = groupname;
+
+ printf("testing NetGroupAdd\n");
+
+ status = NetGroupAdd(hostname, 0, (uint8_t *)&g0, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupAdd");
+ goto out;
+ }
+
+ /* 2nd add must fail */
+
+ status = NetGroupAdd(hostname, 0, (uint8_t *)&g0, &parm_err);
+ if (status == 0) {
+ NETAPI_STATUS(ctx, status, "NetGroupAdd");
+ goto out;
+ }
+
+ /* test enum */
+
+ for (i=0; i<ARRAY_SIZE(enum_levels); i++) {
+
+ status = test_netgroupenum(hostname, enum_levels[i], groupname);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupEnum");
+ goto out;
+ }
+ }
+
+ /* basic queries */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ printf("testing NetGroupGetInfo level %d\n", levels[i]);
+
+ status = NetGroupGetInfo(hostname, groupname, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetGroupGetInfo");
+ goto out;
+ }
+ }
+
+ /* group rename */
+
+ g0.grpi0_name = groupname2;
+
+ printf("testing NetGroupSetInfo level 0\n");
+
+ status = NetGroupSetInfo(hostname, groupname, 0, (uint8_t *)&g0, &parm_err);
+ switch ((int)status) {
+ case 0:
+ break;
+ case 50: /* not supported */
+ case 124: /* not implemented */
+ groupname2 = groupname;
+ goto skip_rename;
+ default:
+ NETAPI_STATUS(ctx, status, "NetGroupSetInfo");
+ goto out;
+ }
+
+ /* should not exist anymore */
+
+ status = NetGroupDel(hostname, groupname);
+ if (status == 0) {
+ NETAPI_STATUS(ctx, status, "NetGroupDel");
+ goto out;
+ }
+
+ skip_rename:
+ /* query info */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ status = NetGroupGetInfo(hostname, groupname2, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetGroupGetInfo");
+ goto out;
+ }
+ }
+
+ /* add user to group */
+
+ status = test_netuseradd(hostname, username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserAdd");
+ goto out;
+ }
+
+ /* should not be member */
+
+ for (i=0; i<ARRAY_SIZE(getmem_levels); i++) {
+
+ status = test_netgroupgetusers(hostname, getmem_levels[i], groupname2, NULL);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupGetUsers");
+ goto out;
+ }
+ }
+
+ printf("testing NetGroupAddUser\n");
+
+ status = NetGroupAddUser(hostname, groupname2, username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupAddUser");
+ goto out;
+ }
+
+ /* should be member */
+
+ for (i=0; i<ARRAY_SIZE(getmem_levels); i++) {
+
+ status = test_netgroupgetusers(hostname, getmem_levels[i], groupname2, username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupGetUsers");
+ goto out;
+ }
+ }
+
+ printf("testing NetGroupDelUser\n");
+
+ status = NetGroupDelUser(hostname, groupname2, username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupDelUser");
+ goto out;
+ }
+
+ /* should not be member */
+
+ status = test_netgroupgetusers(hostname, 0, groupname2, NULL);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupGetUsers");
+ goto out;
+ }
+
+ /* set it again via exlicit member set */
+
+ status = test_netgroupsetusers(hostname, groupname2, 0, 1, &username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupSetUsers");
+ goto out;
+ }
+
+ /* should be member */
+
+ status = test_netgroupgetusers(hostname, 0, groupname2, username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupGetUsers");
+ goto out;
+ }
+#if 0
+ /* wipe out member list */
+
+ status = test_netgroupsetusers(hostname, groupname2, 0, 0, NULL);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupSetUsers");
+ goto out;
+ }
+
+ /* should not be member */
+
+ status = test_netgroupgetusers(hostname, 0, groupname2, NULL);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupGetUsers");
+ goto out;
+ }
+#endif
+ status = NetUserDel(hostname, username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserDel");
+ goto out;
+ }
+
+ /* delete */
+
+ printf("testing NetGroupDel\n");
+
+ status = NetGroupDel(hostname, groupname2);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupDel");
+ goto out;
+ };
+
+ /* should not exist anymore */
+
+ status = NetGroupGetInfo(hostname, groupname2, 0, &buffer);
+ if (status == 0) {
+ NETAPI_STATUS_MSG(ctx, status, "NetGroupGetInfo", "expected failure and error code");
+ goto out;
+ };
+
+ status = 0;
+
+ printf("NetGroup tests succeeded\n");
+ out:
+ if (status != 0) {
+ printf("NetGroup testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ return status;
+}
diff --git a/source3/lib/netapi/tests/netlocalgroup.c b/source3/lib/netapi/tests/netlocalgroup.c
new file mode 100644
index 0000000..76c59c8
--- /dev/null
+++ b/source3/lib/netapi/tests/netlocalgroup.c
@@ -0,0 +1,226 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroup testsuite
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+static NET_API_STATUS test_netlocalgroupenum(const char *hostname,
+ uint32_t level,
+ const char *groupname)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int found_group = 0;
+ const char *current_name = NULL;
+ uint8_t *buffer = NULL;
+ int i;
+
+ struct LOCALGROUP_INFO_0 *info0 = NULL;
+ struct LOCALGROUP_INFO_1 *info1 = NULL;
+
+ printf("testing NetLocalGroupEnum level %d\n", level);
+
+ do {
+ status = NetLocalGroupEnum(hostname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ switch (level) {
+ case 0:
+ info0 = (struct LOCALGROUP_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct LOCALGROUP_INFO_1 *)buffer;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i=0; i<entries_read; i++) {
+
+ switch (level) {
+ case 0:
+ current_name = info0->lgrpi0_name;
+ break;
+ case 1:
+ current_name = info1->lgrpi1_name;
+ break;
+ default:
+ break;
+ }
+
+ if (strcasecmp(current_name, groupname) == 0) {
+ found_group = 1;
+ }
+
+ switch (level) {
+ case 0:
+ info0++;
+ break;
+ case 1:
+ info1++;
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ if (!found_group) {
+ printf("failed to get group\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+NET_API_STATUS netapitest_localgroup(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status = 0;
+ const char *groupname, *groupname2;
+ uint8_t *buffer = NULL;
+ struct LOCALGROUP_INFO_0 g0;
+ uint32_t parm_err = 0;
+ uint32_t levels[] = { 0, 1, 1002 };
+ uint32_t enum_levels[] = { 0, 1 };
+ int i;
+
+ printf("NetLocalgroup tests\n");
+
+ groupname = "torture_test_localgroup";
+ groupname2 = "torture_test_localgroup2";
+
+ /* cleanup */
+ NetLocalGroupDel(hostname, groupname);
+ NetLocalGroupDel(hostname, groupname2);
+
+ /* add a localgroup */
+
+ printf("testing NetLocalGroupAdd\n");
+
+ g0.lgrpi0_name = groupname;
+
+ status = NetLocalGroupAdd(hostname, 0, (uint8_t *)&g0, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupAdd");
+ goto out;
+ };
+
+ /* test enum */
+
+ for (i=0; i<ARRAY_SIZE(enum_levels); i++) {
+
+ status = test_netlocalgroupenum(hostname, enum_levels[i], groupname);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupEnum");
+ goto out;
+ }
+ }
+
+
+ /* basic queries */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ printf("testing NetLocalGroupGetInfo level %d\n", levels[i]);
+
+ status = NetLocalGroupGetInfo(hostname, groupname, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupGetInfo");
+ goto out;
+ };
+ }
+
+ /* alias rename */
+
+ printf("testing NetLocalGroupSetInfo level 0\n");
+
+ g0.lgrpi0_name = groupname2;
+
+ status = NetLocalGroupSetInfo(hostname, groupname, 0, (uint8_t *)&g0, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupSetInfo");
+ goto out;
+ };
+
+ /* should not exist anymore */
+
+ status = NetLocalGroupDel(hostname, groupname);
+ if (status == 0) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupDel");
+ goto out;
+ };
+
+ /* query info */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+ status = NetLocalGroupGetInfo(hostname, groupname2, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupGetInfo");
+ goto out;
+ };
+ }
+
+ /* delete */
+
+ printf("testing NetLocalGroupDel\n");
+
+ status = NetLocalGroupDel(hostname, groupname2);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupDel");
+ goto out;
+ };
+
+ /* should not exist anymore */
+
+ status = NetLocalGroupGetInfo(hostname, groupname2, 0, &buffer);
+ if (status == 0) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupGetInfo");
+ goto out;
+ };
+
+ status = 0;
+
+ printf("NetLocalgroup tests succeeded\n");
+ out:
+ if (status != 0) {
+ printf("NetLocalGroup testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ return status;
+}
diff --git a/source3/lib/netapi/tests/netserver.c b/source3/lib/netapi/tests/netserver.c
new file mode 100644
index 0000000..f7b9286
--- /dev/null
+++ b/source3/lib/netapi/tests/netserver.c
@@ -0,0 +1,61 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetServer testsuite
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+NET_API_STATUS netapitest_server(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status = 0;
+ uint32_t levels[] = { 100, 101, 102, 402, 403, 502, 503, 1005 };
+ int i;
+
+ printf("NetServer tests\n");
+
+ /* basic queries */
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+ uint8_t *buffer = NULL;
+ printf("testing NetServerGetInfo level %d\n", levels[i]);
+
+ status = NetServerGetInfo(hostname, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetServerGetInfo");
+ goto out;
+ }
+ }
+
+ status = 0;
+
+ printf("NetServer tests succeeded\n");
+ out:
+ if (status != 0) {
+ printf("NetServer testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ return status;
+}
diff --git a/source3/lib/netapi/tests/netshare.c b/source3/lib/netapi/tests/netshare.c
new file mode 100644
index 0000000..a518ce9
--- /dev/null
+++ b/source3/lib/netapi/tests/netshare.c
@@ -0,0 +1,250 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShare testsuite
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+static NET_API_STATUS test_netshareenum(const char *hostname,
+ uint32_t level,
+ const char *sharename)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int found_share = 0;
+ const char *current_name = NULL;
+ uint8_t *buffer = NULL;
+ int i;
+
+ struct SHARE_INFO_0 *i0 = NULL;
+ struct SHARE_INFO_1 *i1 = NULL;
+ struct SHARE_INFO_2 *i2 = NULL;
+
+ printf("testing NetShareEnum level %d\n", level);
+
+ do {
+ status = NetShareEnum(hostname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ switch (level) {
+ case 0:
+ i0 = (struct SHARE_INFO_0 *)buffer;
+ break;
+ case 1:
+ i1 = (struct SHARE_INFO_1 *)buffer;
+ break;
+ case 2:
+ i2 = (struct SHARE_INFO_2 *)buffer;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i=0; i<entries_read; i++) {
+
+ switch (level) {
+ case 0:
+ current_name = i0->shi0_netname;
+ break;
+ case 1:
+ current_name = i1->shi1_netname;
+ break;
+ case 2:
+ current_name = i2->shi2_netname;
+ break;
+ default:
+ break;
+ }
+
+ if (strcasecmp(current_name, sharename) == 0) {
+ found_share = 1;
+ }
+
+ switch (level) {
+ case 0:
+ i0++;
+ break;
+ case 1:
+ i1++;
+ break;
+ case 2:
+ i2++;
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ if (!found_share) {
+ printf("failed to get share\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+NET_API_STATUS netapitest_share(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status = 0;
+ const char *sharename, *comment;
+ uint8_t *buffer = NULL;
+ struct SHARE_INFO_2 i2;
+ struct SHARE_INFO_502 i502;
+ struct SHARE_INFO_1004 i1004;
+ struct SHARE_INFO_501 *i501 = NULL;
+ uint32_t parm_err = 0;
+ uint32_t levels[] = { 0, 1, 2, 501, 1005 };
+ uint32_t enum_levels[] = { 0, 1, 2 };
+ int i;
+
+ printf("NetShare tests\n");
+
+ sharename = "torture_test_share";
+
+ /* cleanup */
+ NetShareDel(hostname, sharename, 0);
+
+ /* add a share */
+
+ printf("testing NetShareAdd\n");
+
+ ZERO_STRUCT(i502);
+
+ i502.shi502_netname = sharename;
+ i502.shi502_path = "c:\\";
+
+ status = NetShareAdd(hostname, 502, (uint8_t *)&i502, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetShareAdd");
+ goto out;
+ };
+
+ status = NetShareDel(hostname, sharename, 0);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetShareDel");
+ goto out;
+ };
+
+ ZERO_STRUCT(i2);
+
+ i2.shi2_netname = sharename;
+ i2.shi2_path = "c:\\";
+
+ status = NetShareAdd(hostname, 2, (uint8_t *)&i2, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetShareAdd");
+ goto out;
+ };
+
+ /* test enum */
+
+ for (i=0; i<ARRAY_SIZE(enum_levels); i++) {
+
+ status = test_netshareenum(hostname, enum_levels[i], sharename);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetShareEnum");
+ goto out;
+ }
+ }
+
+ /* basic queries */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ printf("testing NetShareGetInfo level %d\n", levels[i]);
+
+ status = NetShareGetInfo(hostname, sharename, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetShareGetInfo");
+ goto out;
+ }
+ }
+
+
+ comment = "NetApi generated comment";
+
+ i1004.shi1004_remark = comment;
+
+ printf("testing NetShareSetInfo level 1004\n");
+
+ status = NetShareSetInfo(hostname, sharename, 1004, (uint8_t *)&i1004, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetShareSetInfo");
+ goto out;
+ }
+
+ status = NetShareGetInfo(hostname, sharename, 501, (uint8_t **)&i501);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetShareGetInfo");
+ goto out;
+ }
+
+ if (strcasecmp(i501->shi501_remark, comment) != 0) {
+ NETAPI_STATUS(ctx, status, "NetShareGetInfo");
+ goto out;
+ }
+
+ /* delete */
+
+ printf("testing NetShareDel\n");
+
+ status = NetShareDel(hostname, sharename, 0);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetShareDel");
+ goto out;
+ };
+
+ /* should not exist anymore */
+
+ status = NetShareGetInfo(hostname, sharename, 0, &buffer);
+ if (status == 0) {
+ NETAPI_STATUS(ctx, status, "NetShareGetInfo");
+ goto out;
+ };
+
+ status = 0;
+
+ printf("NetShare tests succeeded\n");
+ out:
+ if (status != 0) {
+ printf("NetShare testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ return status;
+}
diff --git a/source3/lib/netapi/tests/netuser.c b/source3/lib/netapi/tests/netuser.c
new file mode 100644
index 0000000..ad2bb53
--- /dev/null
+++ b/source3/lib/netapi/tests/netuser.c
@@ -0,0 +1,462 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUser testsuite
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+static NET_API_STATUS test_netuserenum(const char *hostname,
+ uint32_t level,
+ const char *username)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ const char *current_name = NULL;
+ int found_user = 0;
+ uint8_t *buffer = NULL;
+ int i;
+
+ struct USER_INFO_0 *info0 = NULL;
+ struct USER_INFO_1 *info1 = NULL;
+ struct USER_INFO_2 *info2 = NULL;
+ struct USER_INFO_3 *info3 = NULL;
+ struct USER_INFO_4 *info4 = NULL;
+ struct USER_INFO_10 *info10 = NULL;
+ struct USER_INFO_11 *info11 = NULL;
+ struct USER_INFO_20 *info20 = NULL;
+ struct USER_INFO_23 *info23 = NULL;
+
+ printf("testing NetUserEnum level %d\n", level);
+
+ do {
+ status = NetUserEnum(hostname,
+ level,
+ FILTER_NORMAL_ACCOUNT,
+ &buffer,
+ 120, /*(uint32_t)-1, */
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ switch (level) {
+ case 0:
+ info0 = (struct USER_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct USER_INFO_1 *)buffer;
+ break;
+ case 2:
+ info2 = (struct USER_INFO_2 *)buffer;
+ break;
+ case 3:
+ info3 = (struct USER_INFO_3 *)buffer;
+ break;
+ case 4:
+ info4 = (struct USER_INFO_4 *)buffer;
+ break;
+ case 10:
+ info10 = (struct USER_INFO_10 *)buffer;
+ break;
+ case 11:
+ info11 = (struct USER_INFO_11 *)buffer;
+ break;
+ case 20:
+ info20 = (struct USER_INFO_20 *)buffer;
+ break;
+ case 23:
+ info23 = (struct USER_INFO_23 *)buffer;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i=0; i<entries_read; i++) {
+
+ switch (level) {
+ case 0:
+ current_name = info0->usri0_name;
+ break;
+ case 1:
+ current_name = info1->usri1_name;
+ break;
+ case 2:
+ current_name = info2->usri2_name;
+ break;
+ case 3:
+ current_name = info3->usri3_name;
+ break;
+ case 4:
+ current_name = info4->usri4_name;
+ break;
+ case 10:
+ current_name = info10->usri10_name;
+ break;
+ case 11:
+ current_name = info11->usri11_name;
+ break;
+ case 20:
+ current_name = info20->usri20_name;
+ break;
+ case 23:
+ current_name = info23->usri23_name;
+ break;
+ default:
+ return -1;
+ }
+
+ if (strcasecmp(current_name, username) == 0) {
+ found_user = 1;
+ }
+
+ switch (level) {
+ case 0:
+ info0++;
+ break;
+ case 1:
+ info1++;
+ break;
+ case 2:
+ info2++;
+ break;
+ case 3:
+ info3++;
+ break;
+ case 4:
+ info4++;
+ break;
+ case 10:
+ info10++;
+ break;
+ case 11:
+ info11++;
+ break;
+ case 20:
+ info20++;
+ break;
+ case 23:
+ info23++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ if (!found_user) {
+ printf("failed to get user\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+NET_API_STATUS test_netuseradd(const char *hostname,
+ const char *username)
+{
+ struct USER_INFO_1 u1;
+ uint32_t parm_err = 0;
+
+ ZERO_STRUCT(u1);
+
+ printf("testing NetUserAdd\n");
+
+ u1.usri1_name = username;
+ u1.usri1_password = "W297!832jD8J";
+ u1.usri1_password_age = 0;
+ u1.usri1_priv = 0;
+ u1.usri1_home_dir = NULL;
+ u1.usri1_comment = "User created using Samba NetApi Example code";
+ u1.usri1_flags = 0;
+ u1.usri1_script_path = NULL;
+
+ return NetUserAdd(hostname, 1, (uint8_t *)&u1, &parm_err);
+}
+
+static NET_API_STATUS test_netusermodals(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status;
+ struct USER_MODALS_INFO_0 *u0 = NULL;
+ struct USER_MODALS_INFO_0 *_u0 = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t parm_err = 0;
+ uint32_t levels[] = { 0, 1, 2, 3 };
+ int i = 0;
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ printf("testing NetUserModalsGet level %d\n", levels[i]);
+
+ status = NetUserModalsGet(hostname, levels[i], &buffer);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserModalsGet");
+ return status;
+ }
+ }
+
+ status = NetUserModalsGet(hostname, 0, (uint8_t **)&u0);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserModalsGet");
+ return status;
+ }
+
+ printf("testing NetUserModalsSet\n");
+
+ status = NetUserModalsSet(hostname, 0, (uint8_t *)u0, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserModalsSet");
+ return status;
+ }
+
+ status = NetUserModalsGet(hostname, 0, (uint8_t **)&_u0);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserModalsGet");
+ return status;
+ }
+
+ if (memcmp(u0, _u0, sizeof(*u0)) != 0) {
+ printf("USER_MODALS_INFO_0 struct has changed!!!!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static NET_API_STATUS test_netusergetgroups(const char *hostname,
+ uint32_t level,
+ const char *username,
+ const char *groupname)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ const char *current_name;
+ int found_group = 0;
+ uint8_t *buffer = NULL;
+ int i;
+
+ struct GROUP_USERS_INFO_0 *i0 = NULL;
+ struct GROUP_USERS_INFO_1 *i1 = NULL;
+
+ printf("testing NetUserGetGroups level %d\n", level);
+
+ do {
+ status = NetUserGetGroups(hostname,
+ username,
+ level,
+ &buffer,
+ 120, /*(uint32_t)-1, */
+ &entries_read,
+ &total_entries);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ switch (level) {
+ case 0:
+ i0 = (struct GROUP_USERS_INFO_0 *)buffer;
+ break;
+ case 1:
+ i1 = (struct GROUP_USERS_INFO_1 *)buffer;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i=0; i<entries_read; i++) {
+
+ switch (level) {
+ case 0:
+ current_name = i0->grui0_name;
+ break;
+ case 1:
+ current_name = i1->grui1_name;
+ break;
+ default:
+ return -1;
+ }
+
+ if (groupname && strcasecmp(current_name, groupname) == 0) {
+ found_group = 1;
+ }
+
+ switch (level) {
+ case 0:
+ i0++;
+ break;
+ case 1:
+ i1++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ if (groupname && !found_group) {
+ printf("failed to get membership\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+NET_API_STATUS netapitest_user(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status = 0;
+ const char *username, *username2;
+ uint8_t *buffer = NULL;
+ uint32_t levels[] = { 0, 1, 2, 3, 4, 10, 11, 20, 23 };
+ uint32_t enum_levels[] = { 0, 1, 2, 3, 4, 10, 11, 20, 23 };
+ uint32_t getgr_levels[] = { 0, 1 };
+ int i;
+
+ struct USER_INFO_1007 u1007;
+ uint32_t parm_err = 0;
+
+ printf("NetUser tests\n");
+
+ username = "torture_test_user";
+ username2 = "torture_test_user2";
+
+ /* cleanup */
+ NetUserDel(hostname, username);
+ NetUserDel(hostname, username2);
+
+ /* add a user */
+
+ status = test_netuseradd(hostname, username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserAdd");
+ goto out;
+ }
+
+ /* enum the new user */
+
+ for (i=0; i<ARRAY_SIZE(enum_levels); i++) {
+
+ status = test_netuserenum(hostname, enum_levels[i], username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserEnum");
+ goto out;
+ }
+ }
+
+ /* basic queries */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ printf("testing NetUserGetInfo level %d\n", levels[i]);
+
+ status = NetUserGetInfo(hostname, username, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetUserGetInfo");
+ goto out;
+ }
+ }
+
+ /* testing getgroups */
+
+ for (i=0; i<ARRAY_SIZE(getgr_levels); i++) {
+
+ status = test_netusergetgroups(hostname, getgr_levels[i], username, NULL);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserGetGroups");
+ goto out;
+ }
+ }
+
+ /* modify description */
+
+ printf("testing NetUserSetInfo level %d\n", 1007);
+
+ u1007.usri1007_comment = "NetApi modified user";
+
+ status = NetUserSetInfo(hostname, username, 1007, (uint8_t *)&u1007, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserSetInfo");
+ goto out;
+ }
+
+ /* query info */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+ status = NetUserGetInfo(hostname, username, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetUserGetInfo");
+ goto out;
+ }
+ }
+
+ /* delete */
+
+ printf("testing NetUserDel\n");
+
+ status = NetUserDel(hostname, username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserDel");
+ goto out;
+ }
+
+ /* should not exist anymore */
+
+ status = NetUserGetInfo(hostname, username, 0, &buffer);
+ if (status == 0) {
+ NETAPI_STATUS(ctx, status, "NetUserGetInfo");
+ goto out;
+ }
+
+ status = test_netusermodals(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ status = 0;
+
+ printf("NetUser tests succeeded\n");
+ out:
+ /* cleanup */
+ NetUserDel(hostname, username);
+ NetUserDel(hostname, username2);
+
+ if (status != 0) {
+ printf("NetUser testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ return status;
+}
diff --git a/source3/lib/netapi/tests/netwksta.c b/source3/lib/netapi/tests/netwksta.c
new file mode 100644
index 0000000..2c3f57f
--- /dev/null
+++ b/source3/lib/netapi/tests/netwksta.c
@@ -0,0 +1,62 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetWorkstation testsuite
+ * Copyright (C) Guenther Deschner 2008
+ * Copyright (C) Hans Leidekker 2013
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+NET_API_STATUS netapitest_wksta(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status = 0;
+ uint32_t levels[] = { 100, 101, 102 };
+ int i;
+
+ printf("NetWorkstation tests\n");
+
+ /* basic queries */
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+ uint8_t *buffer = NULL;
+ printf("testing NetWkstaGetInfo level %d\n", levels[i]);
+
+ status = NetWkstaGetInfo(hostname, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetWkstaGetInfo");
+ goto out;
+ }
+ }
+
+ status = 0;
+
+ printf("NetWorkstation tests succeeded\n");
+ out:
+ if (status != 0) {
+ printf("NetWorkstation testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ return status;
+}
diff --git a/source3/lib/netapi/tests/wscript_build b/source3/lib/netapi/tests/wscript_build
new file mode 100644
index 0000000..5e37297
--- /dev/null
+++ b/source3/lib/netapi/tests/wscript_build
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+
+bld.SAMBA_BINARY('netapitest',
+ source='netapitest.c netlocalgroup.c netuser.c netgroup.c netdisplay.c netshare.c netfile.c netserver.c netwksta.c common.c',
+ deps='netapi popt',
+ install=False)
diff --git a/source3/lib/netapi/user.c b/source3/lib/netapi/user.c
new file mode 100644
index 0000000..a7f4c9d
--- /dev/null
+++ b/source3/lib/netapi/user.c
@@ -0,0 +1,3638 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi User Support
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+#include "../librpc/gen_ndr/ndr_samr_c.h"
+#include "rpc_client/init_samr.h"
+#include "../libds/common/flags.h"
+#include "rpc_client/init_lsa.h"
+#include "../libcli/security/security.h"
+#include "../libds/common/flag_mapping.h"
+#include "rpc_client/cli_pipe.h"
+
+/****************************************************************
+****************************************************************/
+
+static void convert_USER_INFO_X_to_samr_user_info21(struct USER_INFO_X *infoX,
+ struct samr_UserInfo21 *info21)
+{
+ uint32_t fields_present = 0;
+ struct samr_LogonHours zero_logon_hours;
+ struct lsa_BinaryString zero_parameters;
+ NTTIME password_age;
+
+ ZERO_STRUCTP(info21);
+ ZERO_STRUCT(zero_logon_hours);
+ ZERO_STRUCT(zero_parameters);
+
+ if (infoX->usriX_flags) {
+ fields_present |= SAMR_FIELD_ACCT_FLAGS;
+ }
+ if (infoX->usriX_name) {
+ fields_present |= SAMR_FIELD_ACCOUNT_NAME;
+ }
+ if (infoX->usriX_password) {
+ fields_present |= SAMR_FIELD_NT_PASSWORD_PRESENT;
+ }
+ if (infoX->usriX_flags) {
+ fields_present |= SAMR_FIELD_ACCT_FLAGS;
+ }
+ if (infoX->usriX_home_dir) {
+ fields_present |= SAMR_FIELD_HOME_DIRECTORY;
+ }
+ if (infoX->usriX_script_path) {
+ fields_present |= SAMR_FIELD_LOGON_SCRIPT;
+ }
+ if (infoX->usriX_comment) {
+ fields_present |= SAMR_FIELD_DESCRIPTION;
+ }
+ if (infoX->usriX_password_age) {
+ fields_present |= SAMR_FIELD_EXPIRED_FLAG;
+ }
+ if (infoX->usriX_full_name) {
+ fields_present |= SAMR_FIELD_FULL_NAME;
+ }
+ if (infoX->usriX_usr_comment) {
+ fields_present |= SAMR_FIELD_COMMENT;
+ }
+ if (infoX->usriX_profile) {
+ fields_present |= SAMR_FIELD_PROFILE_PATH;
+ }
+ if (infoX->usriX_home_dir_drive) {
+ fields_present |= SAMR_FIELD_HOME_DRIVE;
+ }
+ if (infoX->usriX_primary_group_id) {
+ fields_present |= SAMR_FIELD_PRIMARY_GID;
+ }
+ if (infoX->usriX_country_code) {
+ fields_present |= SAMR_FIELD_COUNTRY_CODE;
+ }
+ if (infoX->usriX_workstations) {
+ fields_present |= SAMR_FIELD_WORKSTATIONS;
+ }
+
+ unix_to_nt_time_abs(&password_age, infoX->usriX_password_age);
+
+ /* TODO: infoX->usriX_priv */
+
+ info21->last_logon = 0;
+ info21->last_logoff = 0;
+ info21->last_password_change = 0;
+ info21->acct_expiry = 0;
+ info21->allow_password_change = 0;
+ info21->force_password_change = 0;
+ info21->account_name.string = infoX->usriX_name;
+ info21->full_name.string = infoX->usriX_full_name;
+ info21->home_directory.string = infoX->usriX_home_dir;
+ info21->home_drive.string = infoX->usriX_home_dir_drive;
+ info21->logon_script.string = infoX->usriX_script_path;
+ info21->profile_path.string = infoX->usriX_profile;
+ info21->description.string = infoX->usriX_comment;
+ info21->workstations.string = infoX->usriX_workstations;
+ info21->comment.string = infoX->usriX_usr_comment;
+ info21->parameters = zero_parameters;
+ info21->lm_owf_password = zero_parameters;
+ info21->nt_owf_password = zero_parameters;
+ info21->private_data.string = NULL;
+ info21->buf_count = 0;
+ info21->buffer = NULL;
+ info21->rid = infoX->usriX_user_id;
+ info21->primary_gid = infoX->usriX_primary_group_id;
+ info21->acct_flags = infoX->usriX_flags;
+ info21->fields_present = fields_present;
+ info21->logon_hours = zero_logon_hours;
+ info21->bad_password_count = infoX->usriX_bad_pw_count;
+ info21->logon_count = infoX->usriX_num_logons;
+ info21->country_code = infoX->usriX_country_code;
+ info21->code_page = infoX->usriX_code_page;
+ info21->lm_password_set = 0;
+ info21->nt_password_set = 0;
+ info21->password_expired = infoX->usriX_password_expired;
+ info21->private_data_sensitive = 0;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS construct_USER_INFO_X(uint32_t level,
+ uint8_t *buffer,
+ struct USER_INFO_X *uX)
+{
+ struct USER_INFO_0 *u0 = NULL;
+ struct USER_INFO_1 *u1 = NULL;
+ struct USER_INFO_2 *u2 = NULL;
+ struct USER_INFO_3 *u3 = NULL;
+ struct USER_INFO_1003 *u1003 = NULL;
+ struct USER_INFO_1006 *u1006 = NULL;
+ struct USER_INFO_1007 *u1007 = NULL;
+ struct USER_INFO_1009 *u1009 = NULL;
+ struct USER_INFO_1011 *u1011 = NULL;
+ struct USER_INFO_1012 *u1012 = NULL;
+ struct USER_INFO_1014 *u1014 = NULL;
+ struct USER_INFO_1024 *u1024 = NULL;
+ struct USER_INFO_1051 *u1051 = NULL;
+ struct USER_INFO_1052 *u1052 = NULL;
+ struct USER_INFO_1053 *u1053 = NULL;
+
+ if (!buffer || !uX) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ZERO_STRUCTP(uX);
+
+ switch (level) {
+ case 0:
+ u0 = (struct USER_INFO_0 *)buffer;
+ uX->usriX_name = u0->usri0_name;
+ break;
+ case 1:
+ u1 = (struct USER_INFO_1 *)buffer;
+ uX->usriX_name = u1->usri1_name;
+ uX->usriX_password = u1->usri1_password;
+ uX->usriX_password_age = u1->usri1_password_age;
+ uX->usriX_priv = u1->usri1_priv;
+ uX->usriX_home_dir = u1->usri1_home_dir;
+ uX->usriX_comment = u1->usri1_comment;
+ uX->usriX_flags = u1->usri1_flags;
+ uX->usriX_script_path = u1->usri1_script_path;
+ break;
+ case 2:
+ u2 = (struct USER_INFO_2 *)buffer;
+ uX->usriX_name = u2->usri2_name;
+ uX->usriX_password = u2->usri2_password;
+ uX->usriX_password_age = u2->usri2_password_age;
+ uX->usriX_priv = u2->usri2_priv;
+ uX->usriX_home_dir = u2->usri2_home_dir;
+ uX->usriX_comment = u2->usri2_comment;
+ uX->usriX_flags = u2->usri2_flags;
+ uX->usriX_script_path = u2->usri2_script_path;
+ uX->usriX_auth_flags = u2->usri2_auth_flags;
+ uX->usriX_full_name = u2->usri2_full_name;
+ uX->usriX_usr_comment = u2->usri2_usr_comment;
+ uX->usriX_parms = u2->usri2_parms;
+ uX->usriX_workstations = u2->usri2_workstations;
+ uX->usriX_last_logon = u2->usri2_last_logon;
+ uX->usriX_last_logoff = u2->usri2_last_logoff;
+ uX->usriX_acct_expires = u2->usri2_acct_expires;
+ uX->usriX_max_storage = u2->usri2_max_storage;
+ uX->usriX_units_per_week= u2->usri2_units_per_week;
+ uX->usriX_logon_hours = u2->usri2_logon_hours;
+ uX->usriX_bad_pw_count = u2->usri2_bad_pw_count;
+ uX->usriX_num_logons = u2->usri2_num_logons;
+ uX->usriX_logon_server = u2->usri2_logon_server;
+ uX->usriX_country_code = u2->usri2_country_code;
+ uX->usriX_code_page = u2->usri2_code_page;
+ break;
+ case 3:
+ u3 = (struct USER_INFO_3 *)buffer;
+ uX->usriX_name = u3->usri3_name;
+ uX->usriX_password_age = u3->usri3_password_age;
+ uX->usriX_priv = u3->usri3_priv;
+ uX->usriX_home_dir = u3->usri3_home_dir;
+ uX->usriX_comment = u3->usri3_comment;
+ uX->usriX_flags = u3->usri3_flags;
+ uX->usriX_script_path = u3->usri3_script_path;
+ uX->usriX_auth_flags = u3->usri3_auth_flags;
+ uX->usriX_full_name = u3->usri3_full_name;
+ uX->usriX_usr_comment = u3->usri3_usr_comment;
+ uX->usriX_parms = u3->usri3_parms;
+ uX->usriX_workstations = u3->usri3_workstations;
+ uX->usriX_last_logon = u3->usri3_last_logon;
+ uX->usriX_last_logoff = u3->usri3_last_logoff;
+ uX->usriX_acct_expires = u3->usri3_acct_expires;
+ uX->usriX_max_storage = u3->usri3_max_storage;
+ uX->usriX_units_per_week= u3->usri3_units_per_week;
+ uX->usriX_logon_hours = u3->usri3_logon_hours;
+ uX->usriX_bad_pw_count = u3->usri3_bad_pw_count;
+ uX->usriX_num_logons = u3->usri3_num_logons;
+ uX->usriX_logon_server = u3->usri3_logon_server;
+ uX->usriX_country_code = u3->usri3_country_code;
+ uX->usriX_code_page = u3->usri3_code_page;
+ uX->usriX_user_id = u3->usri3_user_id;
+ uX->usriX_primary_group_id = u3->usri3_primary_group_id;
+ uX->usriX_profile = u3->usri3_profile;
+ uX->usriX_home_dir_drive = u3->usri3_home_dir_drive;
+ uX->usriX_password_expired = u3->usri3_password_expired;
+ break;
+ case 1003:
+ u1003 = (struct USER_INFO_1003 *)buffer;
+ uX->usriX_password = u1003->usri1003_password;
+ break;
+ case 1006:
+ u1006 = (struct USER_INFO_1006 *)buffer;
+ uX->usriX_home_dir = u1006->usri1006_home_dir;
+ break;
+ case 1007:
+ u1007 = (struct USER_INFO_1007 *)buffer;
+ uX->usriX_comment = u1007->usri1007_comment;
+ break;
+ case 1009:
+ u1009 = (struct USER_INFO_1009 *)buffer;
+ uX->usriX_script_path = u1009->usri1009_script_path;
+ break;
+ case 1011:
+ u1011 = (struct USER_INFO_1011 *)buffer;
+ uX->usriX_full_name = u1011->usri1011_full_name;
+ break;
+ case 1012:
+ u1012 = (struct USER_INFO_1012 *)buffer;
+ uX->usriX_usr_comment = u1012->usri1012_usr_comment;
+ break;
+ case 1014:
+ u1014 = (struct USER_INFO_1014 *)buffer;
+ uX->usriX_workstations = u1014->usri1014_workstations;
+ break;
+ case 1024:
+ u1024 = (struct USER_INFO_1024 *)buffer;
+ uX->usriX_country_code = u1024->usri1024_country_code;
+ break;
+ case 1051:
+ u1051 = (struct USER_INFO_1051 *)buffer;
+ uX->usriX_primary_group_id = u1051->usri1051_primary_group_id;
+ break;
+ case 1052:
+ u1052 = (struct USER_INFO_1052 *)buffer;
+ uX->usriX_profile = u1052->usri1052_profile;
+ break;
+ case 1053:
+ u1053 = (struct USER_INFO_1053 *)buffer;
+ uX->usriX_home_dir_drive = u1053->usri1053_home_dir_drive;
+ break;
+ case 4:
+ default:
+ return NT_STATUS_INVALID_INFO_CLASS;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_user_info_USER_INFO_X(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ DATA_BLOB *session_key,
+ struct policy_handle *user_handle,
+ struct USER_INFO_X *uX)
+{
+ union samr_UserInfo user_info;
+ struct samr_UserInfo21 info21;
+ NTSTATUS status, result;
+ struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
+
+ if (!uX) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ convert_USER_INFO_X_to_samr_user_info21(uX, &info21);
+
+ ZERO_STRUCT(user_info);
+
+ if (uX->usriX_password) {
+
+ user_info.info25.info = info21;
+
+ status = init_samr_CryptPasswordEx(uX->usriX_password,
+ session_key,
+ &user_info.info25.password);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
+ user_handle,
+ 25,
+ &user_info,
+ &result);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE)) {
+
+ user_info.info23.info = info21;
+
+ status = init_samr_CryptPassword(uX->usriX_password,
+ session_key,
+ &user_info.info23.password);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
+ user_handle,
+ 23,
+ &user_info,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ } else {
+
+ user_info.info21 = info21;
+
+ status = dcerpc_samr_SetUserInfo(b, mem_ctx,
+ user_handle,
+ 21,
+ &user_info,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ }
+
+ return result;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
+ struct NetUserAdd *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+ struct policy_handle connect_handle, domain_handle, user_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ union samr_UserInfo *user_info = NULL;
+ struct samr_PwInfo pw_info;
+ uint32_t access_granted = 0;
+ uint32_t rid = 0;
+ struct USER_INFO_X uX;
+ struct dcerpc_binding_handle *b = NULL;
+ DATA_BLOB session_key;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(user_handle);
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 1:
+ break;
+ case 2:
+ case 3:
+ case 4:
+ default:
+ werr = WERR_NOT_SUPPORTED;
+ goto done;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
+ SAMR_DOMAIN_ACCESS_CREATE_USER |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, uX.usriX_name);
+
+ status = dcerpc_samr_CreateUser2(b, talloc_tos(),
+ &domain_handle,
+ &lsa_account_name,
+ ACB_NORMAL,
+ SEC_STD_WRITE_DAC |
+ SEC_STD_DELETE |
+ SAMR_USER_ACCESS_SET_PASSWORD |
+ SAMR_USER_ACCESS_SET_ATTRIBUTES |
+ SAMR_USER_ACCESS_GET_ATTRIBUTES,
+ &user_handle,
+ &access_granted,
+ &rid,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = dcerpc_samr_QueryUserInfo(b, talloc_tos(),
+ &user_handle,
+ 16,
+ &user_info,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
+ werr = WERR_INVALID_PARAMETER;
+ goto done;
+ }
+
+ status = dcerpc_samr_GetUserPwInfo(b, talloc_tos(),
+ &user_handle,
+ &pw_info,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ uX.usriX_flags |= ACB_NORMAL;
+
+ status = set_user_info_USER_INFO_X(ctx, pipe_cli,
+ &session_key,
+ &user_handle,
+ &uX);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto failed;
+ }
+
+ werr = WERR_OK;
+ goto done;
+
+ failed:
+ dcerpc_samr_DeleteUser(b, talloc_tos(),
+ &user_handle,
+ &result);
+
+ done:
+ if (is_valid_policy_hnd(&user_handle) && b) {
+ dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
+ struct NetUserAdd *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserAdd);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
+ struct NetUserDel *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+ struct policy_handle connect_handle, builtin_handle, domain_handle, user_handle;
+ struct lsa_String lsa_account_name;
+ struct samr_Ids user_rids, name_types;
+ struct dom_sid2 *domain_sid = NULL;
+ struct dom_sid2 user_sid;
+ struct dcerpc_binding_handle *b = NULL;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(user_handle);
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_samr_OpenDomain(b, talloc_tos(),
+ &connect_handle,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ discard_const_p(struct dom_sid, &global_sid_Builtin),
+ &builtin_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.user_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &user_rids,
+ &name_types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (user_rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (name_types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ status = dcerpc_samr_OpenUser(b, talloc_tos(),
+ &domain_handle,
+ SEC_STD_DELETE,
+ user_rids.ids[0],
+ &user_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
+
+ status = dcerpc_samr_RemoveMemberFromForeignDomain(b, talloc_tos(),
+ &builtin_handle,
+ &user_sid,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = dcerpc_samr_DeleteUser(b, talloc_tos(),
+ &user_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (is_valid_policy_hnd(&user_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
+ struct NetUserDel *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserDel);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct policy_handle *builtin_handle,
+ const char *user_name,
+ const struct dom_sid *domain_sid,
+ uint32_t rid,
+ uint32_t level,
+ struct samr_UserInfo21 **info21,
+ struct sec_desc_buf **sec_desc,
+ uint32_t *auth_flag_p)
+{
+ NTSTATUS status, result;
+
+ struct policy_handle user_handle;
+ union samr_UserInfo *user_info = NULL;
+ struct samr_RidWithAttributeArray *rid_array = NULL;
+ uint32_t access_mask = SEC_STD_READ_CONTROL |
+ SAMR_USER_ACCESS_GET_ATTRIBUTES |
+ SAMR_USER_ACCESS_GET_NAME_ETC;
+ struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
+
+ ZERO_STRUCT(user_handle);
+
+ switch (level) {
+ case 0:
+ break;
+ case 1:
+ access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
+ SAMR_USER_ACCESS_GET_GROUPS;
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 11:
+ access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
+ SAMR_USER_ACCESS_GET_GROUPS |
+ SAMR_USER_ACCESS_GET_LOCALE;
+ break;
+ case 10:
+ case 20:
+ case 23:
+ break;
+ default:
+ return NT_STATUS_INVALID_LEVEL;
+ }
+
+ if (level == 0) {
+ return NT_STATUS_OK;
+ }
+
+ status = dcerpc_samr_OpenUser(b, mem_ctx,
+ domain_handle,
+ access_mask,
+ rid,
+ &user_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ goto done;
+ }
+
+ status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
+ &user_handle,
+ 21,
+ &user_info,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ goto done;
+ }
+
+ status = dcerpc_samr_QuerySecurity(b, mem_ctx,
+ &user_handle,
+ SECINFO_DACL,
+ sec_desc,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ goto done;
+ }
+
+ if (access_mask & SAMR_USER_ACCESS_GET_GROUPS) {
+
+ struct lsa_SidArray sid_array;
+ struct samr_Ids alias_rids;
+ int i;
+ uint32_t auth_flag = 0;
+ struct dom_sid sid;
+
+ status = dcerpc_samr_GetGroupsForUser(b, mem_ctx,
+ &user_handle,
+ &rid_array,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ goto done;
+ }
+
+ sid_array.num_sids = rid_array->count + 1;
+ sid_array.sids = talloc_array(mem_ctx, struct lsa_SidPtr,
+ sid_array.num_sids);
+ NT_STATUS_HAVE_NO_MEMORY(sid_array.sids);
+
+ for (i=0; i<rid_array->count; i++) {
+ sid_compose(&sid, domain_sid, rid_array->rids[i].rid);
+ sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sid);
+ NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
+ }
+
+ sid_compose(&sid, domain_sid, rid);
+ sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sid);
+ NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
+
+ status = dcerpc_samr_GetAliasMembership(b, mem_ctx,
+ builtin_handle,
+ &sid_array,
+ &alias_rids,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ goto done;
+ }
+
+ for (i=0; i<alias_rids.count; i++) {
+ switch (alias_rids.ids[i]) {
+ case 550: /* Print Operators */
+ auth_flag |= AF_OP_PRINT;
+ break;
+ case 549: /* Server Operators */
+ auth_flag |= AF_OP_SERVER;
+ break;
+ case 548: /* Account Operators */
+ auth_flag |= AF_OP_ACCOUNTS;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (auth_flag_p) {
+ *auth_flag_p = auth_flag;
+ }
+ }
+
+ *info21 = &user_info->info21;
+
+ done:
+ if (is_valid_policy_hnd(&user_handle)) {
+ dcerpc_samr_Close(b, mem_ctx, &user_handle, &result);
+ }
+
+ return status;
+}
+
+/****************************************************************
+****************************************************************/
+
+static uint32_t samr_rid_to_priv_level(uint32_t rid)
+{
+ switch (rid) {
+ case DOMAIN_RID_ADMINISTRATOR:
+ return USER_PRIV_ADMIN;
+ case DOMAIN_RID_GUEST:
+ return USER_PRIV_GUEST;
+ default:
+ return USER_PRIV_USER;
+ }
+}
+
+/****************************************************************
+****************************************************************/
+
+static uint32_t samr_acb_flags_to_netapi_flags(uint32_t acb)
+{
+ uint32_t fl = UF_SCRIPT; /* god knows why */
+
+ fl |= ds_acb2uf(acb);
+
+ return fl;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_1(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ struct USER_INFO_1 *i)
+{
+ ZERO_STRUCTP(i);
+ i->usri1_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri1_name);
+ i->usri1_password = NULL;
+ i->usri1_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri1_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri1_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri1_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri1_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri1_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_2(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ uint32_t auth_flag,
+ struct USER_INFO_2 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri2_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri2_name);
+ i->usri2_password = NULL;
+ i->usri2_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri2_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri2_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri2_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri2_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri2_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
+ i->usri2_auth_flags = auth_flag;
+ i->usri2_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri2_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+ i->usri2_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
+ i->usri2_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
+ i->usri2_last_logon = nt_time_to_unix(i21->last_logon);
+ i->usri2_last_logoff = nt_time_to_unix(i21->last_logoff);
+ i->usri2_acct_expires = nt_time_to_unix(i21->acct_expiry);
+ i->usri2_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
+ i->usri2_units_per_week = i21->logon_hours.units_per_week;
+ i->usri2_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
+ i->usri2_bad_pw_count = i21->bad_password_count;
+ i->usri2_num_logons = i21->logon_count;
+ i->usri2_logon_server = talloc_strdup(mem_ctx, "\\\\*");
+ i->usri2_country_code = i21->country_code;
+ i->usri2_code_page = i21->code_page;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_3(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ uint32_t auth_flag,
+ struct USER_INFO_3 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri3_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri3_name);
+ i->usri3_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri3_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri3_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri3_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri3_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri3_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
+ i->usri3_auth_flags = auth_flag;
+ i->usri3_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri3_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+ i->usri3_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
+ i->usri3_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
+ i->usri3_last_logon = nt_time_to_unix(i21->last_logon);
+ i->usri3_last_logoff = nt_time_to_unix(i21->last_logoff);
+ i->usri3_acct_expires = nt_time_to_unix(i21->acct_expiry);
+ i->usri3_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
+ i->usri3_units_per_week = i21->logon_hours.units_per_week;
+ i->usri3_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
+ i->usri3_bad_pw_count = i21->bad_password_count;
+ i->usri3_num_logons = i21->logon_count;
+ i->usri3_logon_server = talloc_strdup(mem_ctx, "\\\\*");
+ i->usri3_country_code = i21->country_code;
+ i->usri3_code_page = i21->code_page;
+ i->usri3_user_id = i21->rid;
+ i->usri3_primary_group_id = i21->primary_gid;
+ i->usri3_profile = talloc_strdup(mem_ctx, i21->profile_path.string);
+ i->usri3_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
+ i->usri3_password_expired = i21->password_expired;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_4(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ uint32_t auth_flag,
+ struct dom_sid *domain_sid,
+ struct USER_INFO_4 *i)
+{
+ struct dom_sid sid;
+
+ ZERO_STRUCTP(i);
+
+ i->usri4_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri4_name);
+ i->usri4_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri4_password = NULL;
+ i->usri4_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri4_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri4_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri4_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri4_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
+ i->usri4_auth_flags = auth_flag;
+ i->usri4_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri4_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+ i->usri4_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
+ i->usri4_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
+ i->usri4_last_logon = nt_time_to_unix(i21->last_logon);
+ i->usri4_last_logoff = nt_time_to_unix(i21->last_logoff);
+ i->usri4_acct_expires = nt_time_to_unix(i21->acct_expiry);
+ i->usri4_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
+ i->usri4_units_per_week = i21->logon_hours.units_per_week;
+ i->usri4_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
+ i->usri4_bad_pw_count = i21->bad_password_count;
+ i->usri4_num_logons = i21->logon_count;
+ i->usri4_logon_server = talloc_strdup(mem_ctx, "\\\\*");
+ i->usri4_country_code = i21->country_code;
+ i->usri4_code_page = i21->code_page;
+ if (!sid_compose(&sid, domain_sid, i21->rid)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ i->usri4_user_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
+ i->usri4_primary_group_id = i21->primary_gid;
+ i->usri4_profile = talloc_strdup(mem_ctx, i21->profile_path.string);
+ i->usri4_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
+ i->usri4_password_expired = i21->password_expired;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_10(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ struct USER_INFO_10 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri10_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri10_name);
+ i->usri10_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri10_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri10_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_11(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ uint32_t auth_flag,
+ struct USER_INFO_11 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri11_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri11_name);
+ i->usri11_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri11_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+ i->usri11_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri11_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri11_auth_flags = auth_flag;
+ i->usri11_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri11_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri11_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
+ i->usri11_last_logon = nt_time_to_unix(i21->last_logon);
+ i->usri11_last_logoff = nt_time_to_unix(i21->last_logoff);
+ i->usri11_bad_pw_count = i21->bad_password_count;
+ i->usri11_num_logons = i21->logon_count;
+ i->usri11_logon_server = talloc_strdup(mem_ctx, "\\\\*");
+ i->usri11_country_code = i21->country_code;
+ i->usri11_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
+ i->usri11_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
+ i->usri11_units_per_week = i21->logon_hours.units_per_week;
+ i->usri11_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
+ i->usri11_code_page = i21->code_page;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_20(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ struct USER_INFO_20 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri20_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri20_name);
+ i->usri20_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri20_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri20_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri20_user_id = i21->rid;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_23(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ struct dom_sid *domain_sid,
+ struct USER_INFO_23 *i)
+{
+ struct dom_sid sid;
+
+ ZERO_STRUCTP(i);
+
+ i->usri23_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri23_name);
+ i->usri23_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri23_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri23_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ if (!sid_compose(&sid, domain_sid, i21->rid)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ i->usri23_user_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct dom_sid *domain_sid,
+ struct policy_handle *domain_handle,
+ struct policy_handle *builtin_handle,
+ const char *user_name,
+ uint32_t rid,
+ uint32_t level,
+ uint8_t **buffer,
+ uint32_t *num_entries)
+{
+ NTSTATUS status;
+
+ struct samr_UserInfo21 *info21 = NULL;
+ struct sec_desc_buf *sec_desc = NULL;
+ uint32_t auth_flag = 0;
+
+ struct USER_INFO_0 info0;
+ struct USER_INFO_1 info1;
+ struct USER_INFO_2 info2;
+ struct USER_INFO_3 info3;
+ struct USER_INFO_4 info4;
+ struct USER_INFO_10 info10;
+ struct USER_INFO_11 info11;
+ struct USER_INFO_20 info20;
+ struct USER_INFO_23 info23;
+
+ switch (level) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 10:
+ case 11:
+ case 20:
+ case 23:
+ break;
+ default:
+ return NT_STATUS_INVALID_LEVEL;
+ }
+
+ if (level == 0) {
+ info0.usri0_name = talloc_strdup(mem_ctx, user_name);
+ NT_STATUS_HAVE_NO_MEMORY(info0.usri0_name);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_0, info0,
+ (struct USER_INFO_0 **)buffer, num_entries);
+
+ return NT_STATUS_OK;
+ }
+
+ status = libnetapi_samr_lookup_user(mem_ctx, pipe_cli,
+ domain_handle,
+ builtin_handle,
+ user_name,
+ domain_sid,
+ rid,
+ level,
+ &info21,
+ &sec_desc,
+ &auth_flag);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ switch (level) {
+ case 1:
+ status = info21_to_USER_INFO_1(mem_ctx, info21, &info1);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_1, info1,
+ (struct USER_INFO_1 **)buffer, num_entries);
+
+ break;
+ case 2:
+ status = info21_to_USER_INFO_2(mem_ctx, info21, auth_flag, &info2);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_2, info2,
+ (struct USER_INFO_2 **)buffer, num_entries);
+
+ break;
+ case 3:
+ status = info21_to_USER_INFO_3(mem_ctx, info21, auth_flag, &info3);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_3, info3,
+ (struct USER_INFO_3 **)buffer, num_entries);
+
+ break;
+ case 4:
+ status = info21_to_USER_INFO_4(mem_ctx, info21, auth_flag, domain_sid, &info4);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_4, info4,
+ (struct USER_INFO_4 **)buffer, num_entries);
+
+ break;
+ case 10:
+ status = info21_to_USER_INFO_10(mem_ctx, info21, &info10);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
+ (struct USER_INFO_10 **)buffer, num_entries);
+
+ break;
+ case 11:
+ status = info21_to_USER_INFO_11(mem_ctx, info21, auth_flag, &info11);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_11, info11,
+ (struct USER_INFO_11 **)buffer, num_entries);
+
+ break;
+ case 20:
+ status = info21_to_USER_INFO_20(mem_ctx, info21, &info20);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
+ (struct USER_INFO_20 **)buffer, num_entries);
+
+ break;
+ case 23:
+ status = info21_to_USER_INFO_23(mem_ctx, info21, domain_sid, &info23);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, info23,
+ (struct USER_INFO_23 **)buffer, num_entries);
+ break;
+ default:
+ return NT_STATUS_INVALID_LEVEL;
+ }
+
+ done:
+ return status;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
+ struct NetUserEnum *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ struct policy_handle domain_handle, builtin_handle;
+ struct samr_SamArray *sam = NULL;
+ uint32_t filter = ACB_NORMAL;
+ int i;
+ uint32_t entries_read = 0;
+
+ NTSTATUS status;
+ NTSTATUS result = NT_STATUS_OK;
+ WERROR werr;
+ struct dcerpc_binding_handle *b = NULL;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(builtin_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ *r->out.buffer = NULL;
+ *r->out.entries_read = 0;
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 10:
+ case 11:
+ case 20:
+ case 23:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
+ SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
+ SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ switch (r->in.filter) {
+ case FILTER_NORMAL_ACCOUNT:
+ filter = ACB_NORMAL;
+ break;
+ case FILTER_TEMP_DUPLICATE_ACCOUNT:
+ filter = ACB_TEMPDUP;
+ break;
+ case FILTER_INTERDOMAIN_TRUST_ACCOUNT:
+ filter = ACB_DOMTRUST;
+ break;
+ case FILTER_WORKSTATION_TRUST_ACCOUNT:
+ filter = ACB_WSTRUST;
+ break;
+ case FILTER_SERVER_TRUST_ACCOUNT:
+ filter = ACB_SVRTRUST;
+ break;
+ default:
+ break;
+ }
+
+ status = dcerpc_samr_EnumDomainUsers(b,
+ ctx,
+ &domain_handle,
+ r->in.resume_handle,
+ filter,
+ &sam,
+ r->in.prefmaxlen,
+ &entries_read,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ werr = ntstatus_to_werror(result);
+ if (NT_STATUS_IS_ERR(result)) {
+ goto done;
+ }
+
+ for (i=0; i < sam->count; i++) {
+
+ status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
+ domain_sid,
+ &domain_handle,
+ &builtin_handle,
+ sam->entries[i].name.string,
+ sam->entries[i].idx,
+ r->in.level,
+ r->out.buffer,
+ r->out.entries_read);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ done:
+ /* if last query */
+ if (NT_STATUS_IS_OK(result) ||
+ NT_STATUS_IS_ERR(result)) {
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
+ struct NetUserEnum *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserEnum);
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR convert_samr_dispinfo_to_NET_DISPLAY_USER(TALLOC_CTX *mem_ctx,
+ struct samr_DispInfoGeneral *info,
+ uint32_t *entries_read,
+ void **buffer)
+{
+ struct NET_DISPLAY_USER *user = NULL;
+ int i;
+
+ user = talloc_zero_array(mem_ctx,
+ struct NET_DISPLAY_USER,
+ info->count);
+ W_ERROR_HAVE_NO_MEMORY(user);
+
+ for (i = 0; i < info->count; i++) {
+ user[i].usri1_name = talloc_strdup(mem_ctx,
+ info->entries[i].account_name.string);
+ user[i].usri1_comment = talloc_strdup(mem_ctx,
+ info->entries[i].description.string);
+ user[i].usri1_flags =
+ info->entries[i].acct_flags;
+ user[i].usri1_full_name = talloc_strdup(mem_ctx,
+ info->entries[i].full_name.string);
+ user[i].usri1_user_id =
+ info->entries[i].rid;
+ user[i].usri1_next_index =
+ info->entries[i].idx;
+
+ if (!user[i].usri1_name) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+ }
+
+ *buffer = talloc_memdup(mem_ctx, user,
+ sizeof(struct NET_DISPLAY_USER) * info->count);
+ W_ERROR_HAVE_NO_MEMORY(*buffer);
+
+ *entries_read = info->count;
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(TALLOC_CTX *mem_ctx,
+ struct samr_DispInfoFull *info,
+ uint32_t *entries_read,
+ void **buffer)
+{
+ struct NET_DISPLAY_MACHINE *machine = NULL;
+ int i;
+
+ machine = talloc_zero_array(mem_ctx,
+ struct NET_DISPLAY_MACHINE,
+ info->count);
+ W_ERROR_HAVE_NO_MEMORY(machine);
+
+ for (i = 0; i < info->count; i++) {
+ machine[i].usri2_name = talloc_strdup(mem_ctx,
+ info->entries[i].account_name.string);
+ machine[i].usri2_comment = talloc_strdup(mem_ctx,
+ info->entries[i].description.string);
+ machine[i].usri2_flags =
+ info->entries[i].acct_flags;
+ machine[i].usri2_user_id =
+ info->entries[i].rid;
+ machine[i].usri2_next_index =
+ info->entries[i].idx;
+
+ if (!machine[i].usri2_name) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+ }
+
+ *buffer = talloc_memdup(mem_ctx, machine,
+ sizeof(struct NET_DISPLAY_MACHINE) * info->count);
+ W_ERROR_HAVE_NO_MEMORY(*buffer);
+
+ *entries_read = info->count;
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
+ struct samr_DispInfoFullGroups *info,
+ uint32_t *entries_read,
+ void **buffer)
+{
+ struct NET_DISPLAY_GROUP *group = NULL;
+ int i;
+
+ group = talloc_zero_array(mem_ctx,
+ struct NET_DISPLAY_GROUP,
+ info->count);
+ W_ERROR_HAVE_NO_MEMORY(group);
+
+ for (i = 0; i < info->count; i++) {
+ group[i].grpi3_name = talloc_strdup(mem_ctx,
+ info->entries[i].account_name.string);
+ group[i].grpi3_comment = talloc_strdup(mem_ctx,
+ info->entries[i].description.string);
+ group[i].grpi3_group_id =
+ info->entries[i].rid;
+ group[i].grpi3_attributes =
+ info->entries[i].acct_flags;
+ group[i].grpi3_next_index =
+ info->entries[i].idx;
+
+ if (!group[i].grpi3_name) {
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+ }
+
+ *buffer = talloc_memdup(mem_ctx, group,
+ sizeof(struct NET_DISPLAY_GROUP) * info->count);
+ W_ERROR_HAVE_NO_MEMORY(*buffer);
+
+ *entries_read = info->count;
+
+ return WERR_OK;
+
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
+ union samr_DispInfo *info,
+ uint32_t level,
+ uint32_t *entries_read,
+ void **buffer)
+{
+ switch (level) {
+ case 1:
+ return convert_samr_dispinfo_to_NET_DISPLAY_USER(mem_ctx,
+ &info->info1,
+ entries_read,
+ buffer);
+ case 2:
+ return convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(mem_ctx,
+ &info->info2,
+ entries_read,
+ buffer);
+ case 3:
+ return convert_samr_dispinfo_to_NET_DISPLAY_GROUP(mem_ctx,
+ &info->info3,
+ entries_read,
+ buffer);
+ default:
+ break;
+ }
+
+ return WERR_INVALID_LEVEL;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
+ struct NetQueryDisplayInformation *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ struct policy_handle domain_handle;
+ union samr_DispInfo info;
+ struct dcerpc_binding_handle *b = NULL;
+
+ uint32_t total_size = 0;
+ uint32_t returned_size = 0;
+
+ NTSTATUS status;
+ NTSTATUS result = NT_STATUS_OK;
+ WERROR werr;
+ WERROR werr_tmp;
+
+ *r->out.entries_read = 0;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ switch (r->in.level) {
+ case 1:
+ case 2:
+ case 3:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
+ SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_samr_QueryDisplayInfo2(b,
+ ctx,
+ &domain_handle,
+ r->in.level,
+ r->in.idx,
+ r->in.entries_requested,
+ r->in.prefmaxlen,
+ &total_size,
+ &returned_size,
+ &info,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ werr = ntstatus_to_werror(result);
+ if (NT_STATUS_IS_ERR(result)) {
+ goto done;
+ }
+
+ werr_tmp = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
+ r->in.level,
+ r->out.entries_read,
+ r->out.buffer);
+ if (!W_ERROR_IS_OK(werr_tmp)) {
+ werr = werr_tmp;
+ }
+ done:
+ /* if last query */
+ if (NT_STATUS_IS_OK(result) ||
+ NT_STATUS_IS_ERR(result)) {
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+ }
+
+ return werr;
+
+}
+
+/****************************************************************
+****************************************************************/
+
+
+WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
+ struct NetQueryDisplayInformation *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetQueryDisplayInformation);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
+ struct NetUserChangePassword *r)
+{
+ return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
+ struct NetUserChangePassword *r)
+{
+ return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetUserGetInfo *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+
+ struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct samr_Ids user_rids, name_types;
+ uint32_t num_entries = 0;
+ struct dcerpc_binding_handle *b = NULL;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(user_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 10:
+ case 11:
+ case 20:
+ case 23:
+ break;
+ default:
+ werr = WERR_INVALID_LEVEL;
+ goto done;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
+ SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.user_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &user_rids,
+ &name_types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (user_rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (name_types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
+ domain_sid,
+ &domain_handle,
+ &builtin_handle,
+ r->in.user_name,
+ user_rids.ids[0],
+ r->in.level,
+ r->out.buffer,
+ &num_entries);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ if (is_valid_policy_hnd(&user_handle) && b) {
+ dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetUserGetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetUserSetInfo *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status, result;
+ WERROR werr;
+
+ struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct samr_Ids user_rids, name_types;
+ uint32_t user_mask = 0;
+
+ struct USER_INFO_X uX;
+ struct dcerpc_binding_handle *b = NULL;
+ DATA_BLOB session_key;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(user_handle);
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
+ break;
+ case 1003:
+ user_mask = SAMR_USER_ACCESS_SET_PASSWORD;
+ break;
+ case 1006:
+ case 1007:
+ case 1009:
+ case 1011:
+ case 1014:
+ case 1052:
+ case 1053:
+ user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
+ break;
+ case 1012:
+ case 1024:
+ user_mask = SAMR_USER_ACCESS_SET_LOC_COM;
+ break;
+ case 1051:
+ user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES |
+ SAMR_USER_ACCESS_GET_GROUPS;
+ break;
+ case 3:
+ user_mask = SEC_STD_READ_CONTROL |
+ SEC_STD_WRITE_DAC |
+ SAMR_USER_ACCESS_GET_GROUPS |
+ SAMR_USER_ACCESS_SET_PASSWORD |
+ SAMR_USER_ACCESS_SET_ATTRIBUTES |
+ SAMR_USER_ACCESS_GET_ATTRIBUTES |
+ SAMR_USER_ACCESS_SET_LOC_COM;
+ break;
+ case 1:
+ case 2:
+ case 4:
+ case 21:
+ case 22:
+ case 1005:
+ case 1008:
+ case 1010:
+ case 1017:
+ case 1020:
+ werr = WERR_NOT_SUPPORTED;
+ goto done;
+ default:
+ werr = WERR_INVALID_LEVEL;
+ goto done;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
+ SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.user_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &user_rids,
+ &name_types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (user_rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (name_types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ status = dcerpc_samr_OpenUser(b, talloc_tos(),
+ &domain_handle,
+ user_mask,
+ user_rids.ids[0],
+ &user_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = set_user_info_USER_INFO_X(ctx, pipe_cli,
+ &session_key,
+ &user_handle,
+ &uX);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (is_valid_policy_hnd(&user_handle) && b) {
+ dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetUserSetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct samr_DomInfo1 *info1,
+ struct samr_DomInfo3 *info3,
+ struct samr_DomInfo5 *info5,
+ struct samr_DomInfo6 *info6,
+ struct samr_DomInfo7 *info7,
+ struct samr_DomInfo12 *info12)
+{
+ NTSTATUS status, result;
+ union samr_DomainInfo *dom_info = NULL;
+ struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
+
+ if (info1) {
+ status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
+ domain_handle,
+ 1,
+ &dom_info,
+ &result);
+ NT_STATUS_NOT_OK_RETURN(status);
+ NT_STATUS_NOT_OK_RETURN(result);
+
+ *info1 = dom_info->info1;
+ }
+
+ if (info3) {
+ status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
+ domain_handle,
+ 3,
+ &dom_info,
+ &result);
+ NT_STATUS_NOT_OK_RETURN(status);
+ NT_STATUS_NOT_OK_RETURN(result);
+
+ *info3 = dom_info->info3;
+ }
+
+ if (info5) {
+ status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
+ domain_handle,
+ 5,
+ &dom_info,
+ &result);
+ NT_STATUS_NOT_OK_RETURN(status);
+ NT_STATUS_NOT_OK_RETURN(result);
+
+ *info5 = dom_info->info5;
+ }
+
+ if (info6) {
+ status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
+ domain_handle,
+ 6,
+ &dom_info,
+ &result);
+ NT_STATUS_NOT_OK_RETURN(status);
+ NT_STATUS_NOT_OK_RETURN(result);
+
+ *info6 = dom_info->info6;
+ }
+
+ if (info7) {
+ status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
+ domain_handle,
+ 7,
+ &dom_info,
+ &result);
+ NT_STATUS_NOT_OK_RETURN(status);
+ NT_STATUS_NOT_OK_RETURN(result);
+
+ *info7 = dom_info->info7;
+ }
+
+ if (info12) {
+ status = dcerpc_samr_QueryDomainInfo2(b, mem_ctx,
+ domain_handle,
+ 12,
+ &dom_info,
+ &result);
+ NT_STATUS_NOT_OK_RETURN(status);
+ NT_STATUS_NOT_OK_RETURN(result);
+
+ *info12 = dom_info->info12;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_0(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_0 *info0)
+{
+ NTSTATUS status;
+ struct samr_DomInfo1 dom_info1;
+ struct samr_DomInfo3 dom_info3;
+
+ ZERO_STRUCTP(info0);
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info1,
+ &dom_info3,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ info0->usrmod0_min_passwd_len =
+ dom_info1.min_password_length;
+ info0->usrmod0_max_passwd_age =
+ nt_time_to_unix_abs((NTTIME *)&dom_info1.max_password_age);
+ info0->usrmod0_min_passwd_age =
+ nt_time_to_unix_abs((NTTIME *)&dom_info1.min_password_age);
+ info0->usrmod0_password_hist_len =
+ dom_info1.password_history_length;
+
+ info0->usrmod0_force_logoff =
+ nt_time_to_unix_abs(&dom_info3.force_logoff_time);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_1(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_1 *info1)
+{
+ NTSTATUS status;
+ struct samr_DomInfo6 dom_info6;
+ struct samr_DomInfo7 dom_info7;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ NULL,
+ NULL,
+ &dom_info6,
+ &dom_info7,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ info1->usrmod1_primary =
+ talloc_strdup(mem_ctx, dom_info6.primary.string);
+
+ info1->usrmod1_role = dom_info7.role;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_2(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct dom_sid *domain_sid,
+ struct USER_MODALS_INFO_2 *info2)
+{
+ NTSTATUS status;
+ struct samr_DomInfo5 dom_info5;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ NULL,
+ &dom_info5,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ info2->usrmod2_domain_name =
+ talloc_strdup(mem_ctx, dom_info5.domain_name.string);
+ info2->usrmod2_domain_id =
+ (struct domsid *)dom_sid_dup(mem_ctx, domain_sid);
+
+ NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_name);
+ NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_id);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_3(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_3 *info3)
+{
+ NTSTATUS status;
+ struct samr_DomInfo12 dom_info12;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &dom_info12);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ info3->usrmod3_lockout_duration =
+ nt_time_to_unix_abs(&dom_info12.lockout_duration);
+ info3->usrmod3_lockout_observation_window =
+ nt_time_to_unix_abs(&dom_info12.lockout_window);
+ info3->usrmod3_lockout_threshold =
+ dom_info12.lockout_threshold;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_to_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ uint32_t level,
+ struct policy_handle *domain_handle,
+ struct dom_sid *domain_sid,
+ uint8_t **buffer)
+{
+ NTSTATUS status;
+
+ struct USER_MODALS_INFO_0 info0;
+ struct USER_MODALS_INFO_1 info1;
+ struct USER_MODALS_INFO_2 info2;
+ struct USER_MODALS_INFO_3 info3;
+
+ if (!buffer) {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ switch (level) {
+ case 0:
+ status = query_USER_MODALS_INFO_0(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &info0);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0,
+ sizeof(info0));
+ break;
+
+ case 1:
+ status = query_USER_MODALS_INFO_1(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &info1);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1,
+ sizeof(info1));
+ break;
+ case 2:
+ status = query_USER_MODALS_INFO_2(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ domain_sid,
+ &info2);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2,
+ sizeof(info2));
+ break;
+ case 3:
+ status = query_USER_MODALS_INFO_3(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &info3);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3,
+ sizeof(info3));
+ break;
+ default:
+ break;
+ }
+
+ NT_STATUS_HAVE_NO_MEMORY(*buffer);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
+ struct NetUserModalsGet *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+
+ struct policy_handle connect_handle, domain_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
+ break;
+ case 1:
+ case 2:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
+ break;
+ case 3:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1;
+ break;
+ default:
+ werr = WERR_INVALID_LEVEL;
+ goto done;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ access_mask,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ /* 0: 1 + 3 */
+ /* 1: 6 + 7 */
+ /* 2: 5 */
+ /* 3: 12 (DomainInfo2) */
+
+ status = query_USER_MODALS_INFO_to_buffer(ctx,
+ pipe_cli,
+ r->in.level,
+ &domain_handle,
+ domain_sid,
+ r->out.buffer);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
+ struct NetUserModalsGet *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsGet);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct samr_DomInfo1 *info1,
+ struct samr_DomInfo3 *info3,
+ struct samr_DomInfo12 *info12)
+{
+ NTSTATUS status, result;
+ union samr_DomainInfo dom_info;
+ struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
+
+ if (info1) {
+
+ ZERO_STRUCT(dom_info);
+
+ dom_info.info1 = *info1;
+
+ status = dcerpc_samr_SetDomainInfo(b, mem_ctx,
+ domain_handle,
+ 1,
+ &dom_info,
+ &result);
+ NT_STATUS_NOT_OK_RETURN(status);
+ NT_STATUS_NOT_OK_RETURN(result);
+ }
+
+ if (info3) {
+
+ ZERO_STRUCT(dom_info);
+
+ dom_info.info3 = *info3;
+
+ status = dcerpc_samr_SetDomainInfo(b, mem_ctx,
+ domain_handle,
+ 3,
+ &dom_info,
+ &result);
+
+ NT_STATUS_NOT_OK_RETURN(status);
+ NT_STATUS_NOT_OK_RETURN(result);
+ }
+
+ if (info12) {
+
+ ZERO_STRUCT(dom_info);
+
+ dom_info.info12 = *info12;
+
+ status = dcerpc_samr_SetDomainInfo(b, mem_ctx,
+ domain_handle,
+ 12,
+ &dom_info,
+ &result);
+
+ NT_STATUS_NOT_OK_RETURN(status);
+ NT_STATUS_NOT_OK_RETURN(result);
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_0_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_0 *info0)
+{
+ NTSTATUS status;
+ struct samr_DomInfo1 dom_info_1;
+ struct samr_DomInfo3 dom_info_3;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ &dom_info_3,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ dom_info_1.min_password_length =
+ info0->usrmod0_min_passwd_len;
+ dom_info_1.password_history_length =
+ info0->usrmod0_password_hist_len;
+
+ unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
+ info0->usrmod0_max_passwd_age);
+ unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
+ info0->usrmod0_min_passwd_age);
+
+ unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
+ info0->usrmod0_force_logoff);
+
+ return set_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ &dom_info_3,
+ NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_3_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_3 *info3)
+{
+ NTSTATUS status;
+ struct samr_DomInfo12 dom_info_12;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &dom_info_12);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_duration,
+ info3->usrmod3_lockout_duration);
+ unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_window,
+ info3->usrmod3_lockout_observation_window);
+ dom_info_12.lockout_threshold = info3->usrmod3_lockout_threshold;
+
+ return set_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ NULL,
+ &dom_info_12);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_1001_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_1001 *info1001)
+{
+ NTSTATUS status;
+ struct samr_DomInfo1 dom_info_1;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ dom_info_1.min_password_length =
+ info1001->usrmod1001_min_passwd_len;
+
+ return set_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_1002_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_1002 *info1002)
+{
+ NTSTATUS status;
+ struct samr_DomInfo1 dom_info_1;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
+ info1002->usrmod1002_max_passwd_age);
+
+ return set_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_1003_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_1003 *info1003)
+{
+ NTSTATUS status;
+ struct samr_DomInfo1 dom_info_1;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
+ info1003->usrmod1003_min_passwd_age);
+
+ return set_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_1004_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_1004 *info1004)
+{
+ NTSTATUS status;
+ struct samr_DomInfo3 dom_info_3;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ &dom_info_3,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
+ info1004->usrmod1004_force_logoff);
+
+ return set_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ &dom_info_3,
+ NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_1005_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_1005 *info1005)
+{
+ NTSTATUS status;
+ struct samr_DomInfo1 dom_info_1;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ dom_info_1.password_history_length =
+ info1005->usrmod1005_password_hist_len;
+
+ return set_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ uint32_t level,
+ struct policy_handle *domain_handle,
+ struct dom_sid *domain_sid,
+ uint8_t *buffer)
+{
+ struct USER_MODALS_INFO_0 *info0;
+ struct USER_MODALS_INFO_3 *info3;
+ struct USER_MODALS_INFO_1001 *info1001;
+ struct USER_MODALS_INFO_1002 *info1002;
+ struct USER_MODALS_INFO_1003 *info1003;
+ struct USER_MODALS_INFO_1004 *info1004;
+ struct USER_MODALS_INFO_1005 *info1005;
+
+ if (!buffer) {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ switch (level) {
+ case 0:
+ info0 = (struct USER_MODALS_INFO_0 *)buffer;
+ return set_USER_MODALS_INFO_0_buffer(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ info0);
+ case 3:
+ info3 = (struct USER_MODALS_INFO_3 *)buffer;
+ return set_USER_MODALS_INFO_3_buffer(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ info3);
+ case 1001:
+ info1001 = (struct USER_MODALS_INFO_1001 *)buffer;
+ return set_USER_MODALS_INFO_1001_buffer(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ info1001);
+ case 1002:
+ info1002 = (struct USER_MODALS_INFO_1002 *)buffer;
+ return set_USER_MODALS_INFO_1002_buffer(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ info1002);
+ case 1003:
+ info1003 = (struct USER_MODALS_INFO_1003 *)buffer;
+ return set_USER_MODALS_INFO_1003_buffer(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ info1003);
+ case 1004:
+ info1004 = (struct USER_MODALS_INFO_1004 *)buffer;
+ return set_USER_MODALS_INFO_1004_buffer(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ info1004);
+ case 1005:
+ info1005 = (struct USER_MODALS_INFO_1005 *)buffer;
+ return set_USER_MODALS_INFO_1005_buffer(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ info1005);
+
+ default:
+ break;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
+ struct NetUserModalsSet *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+
+ struct policy_handle connect_handle, domain_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
+ SAMR_DOMAIN_ACCESS_SET_INFO_1 |
+ SAMR_DOMAIN_ACCESS_SET_INFO_2;
+ break;
+ case 3:
+ case 1001:
+ case 1002:
+ case 1003:
+ case 1005:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
+ SAMR_DOMAIN_ACCESS_SET_INFO_1;
+ break;
+ case 1004:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
+ SAMR_DOMAIN_ACCESS_SET_INFO_2;
+ break;
+ case 1:
+ case 2:
+ case 1006:
+ case 1007:
+ werr = WERR_NOT_SUPPORTED;
+ break;
+ default:
+ werr = WERR_INVALID_LEVEL;
+ goto done;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ access_mask,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = set_USER_MODALS_INFO_buffer(ctx,
+ pipe_cli,
+ r->in.level,
+ &domain_handle,
+ domain_sid,
+ r->in.buffer);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
+ struct NetUserModalsSet *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsSet);
+}
+
+/****************************************************************
+****************************************************************/
+
+NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ const char *group_name,
+ uint32_t attributes,
+ uint8_t **buffer,
+ uint32_t *num_entries)
+{
+ struct GROUP_USERS_INFO_0 u0;
+ struct GROUP_USERS_INFO_1 u1;
+
+ switch (level) {
+ case 0:
+ if (group_name) {
+ u0.grui0_name = talloc_strdup(mem_ctx, group_name);
+ NT_STATUS_HAVE_NO_MEMORY(u0.grui0_name);
+ } else {
+ u0.grui0_name = NULL;
+ }
+
+ ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_0, u0,
+ (struct GROUP_USERS_INFO_0 **)buffer, num_entries);
+ break;
+ case 1:
+ if (group_name) {
+ u1.grui1_name = talloc_strdup(mem_ctx, group_name);
+ NT_STATUS_HAVE_NO_MEMORY(u1.grui1_name);
+ } else {
+ u1.grui1_name = NULL;
+ }
+
+ u1.grui1_attributes = attributes;
+
+ ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_1, u1,
+ (struct GROUP_USERS_INFO_1 **)buffer, num_entries);
+ break;
+ default:
+ return NT_STATUS_INVALID_INFO_CLASS;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
+ struct NetUserGetGroups *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle, domain_handle, user_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct samr_Ids user_rids, name_types;
+ struct samr_RidWithAttributeArray *rid_array = NULL;
+ struct lsa_Strings names;
+ struct samr_Ids types;
+ uint32_t *rids = NULL;
+
+ int i;
+ uint32_t entries_read = 0;
+
+ NTSTATUS status;
+ NTSTATUS result = NT_STATUS_OK;
+ WERROR werr;
+ struct dcerpc_binding_handle *b = NULL;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ *r->out.buffer = NULL;
+ *r->out.entries_read = 0;
+ *r->out.total_entries = 0;
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.user_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &user_rids,
+ &name_types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (user_rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (name_types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ status = dcerpc_samr_OpenUser(b, talloc_tos(),
+ &domain_handle,
+ SAMR_USER_ACCESS_GET_GROUPS,
+ user_rids.ids[0],
+ &user_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = dcerpc_samr_GetGroupsForUser(b, talloc_tos(),
+ &user_handle,
+ &rid_array,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ rids = talloc_array(ctx, uint32_t, rid_array->count);
+ if (!rids) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ for (i=0; i < rid_array->count; i++) {
+ rids[i] = rid_array->rids[i].rid;
+ }
+
+ status = dcerpc_samr_LookupRids(b, talloc_tos(),
+ &domain_handle,
+ rid_array->count,
+ rids,
+ &names,
+ &types,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (!NT_STATUS_IS_OK(result) &&
+ !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
+ werr = ntstatus_to_werror(result);
+ goto done;
+ }
+ if (names.count != rid_array->count) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (types.count != rid_array->count) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ for (i=0; i < names.count; i++) {
+ status = add_GROUP_USERS_INFO_X_buffer(ctx,
+ r->in.level,
+ names.names[i].string,
+ rid_array->rids[i].attributes,
+ r->out.buffer,
+ &entries_read);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ *r->out.entries_read = entries_read;
+ *r->out.total_entries = entries_read;
+
+ done:
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
+ struct NetUserGetGroups *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetGroups);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx,
+ struct NetUserSetGroups *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle, domain_handle, user_handle, group_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct samr_Ids user_rids, name_types;
+ struct samr_Ids group_rids;
+ struct samr_RidWithAttributeArray *rid_array = NULL;
+ struct lsa_String *lsa_names = NULL;
+
+ uint32_t *add_rids = NULL;
+ uint32_t *del_rids = NULL;
+ size_t num_add_rids = 0;
+ size_t num_del_rids = 0;
+
+ uint32_t *member_rids = NULL;
+
+ struct GROUP_USERS_INFO_0 *i0 = NULL;
+ struct GROUP_USERS_INFO_1 *i1 = NULL;
+
+ int i, k;
+
+ NTSTATUS status;
+ NTSTATUS result = NT_STATUS_OK;
+ WERROR werr;
+ struct dcerpc_binding_handle *b = NULL;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.user_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &user_rids,
+ &name_types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (user_rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (name_types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ status = dcerpc_samr_OpenUser(b, talloc_tos(),
+ &domain_handle,
+ SAMR_USER_ACCESS_GET_GROUPS,
+ user_rids.ids[0],
+ &user_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
+ break;
+ case 1:
+ i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
+ break;
+ }
+
+ lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
+ if (!lsa_names) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ for (i=0; i < r->in.num_entries; i++) {
+
+ switch (r->in.level) {
+ case 0:
+ init_lsa_String(&lsa_names[i], i0->grui0_name);
+ i0++;
+ break;
+ case 1:
+ init_lsa_String(&lsa_names[i], i1->grui1_name);
+ i1++;
+ break;
+ }
+ }
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ r->in.num_entries,
+ lsa_names,
+ &group_rids,
+ &name_types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (group_rids.count != r->in.num_entries) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (name_types.count != r->in.num_entries) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ member_rids = group_rids.ids;
+
+ status = dcerpc_samr_GetGroupsForUser(b, talloc_tos(),
+ &user_handle,
+ &rid_array,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ /* add list */
+
+ for (i=0; i < r->in.num_entries; i++) {
+ bool already_member = false;
+ for (k=0; k < rid_array->count; k++) {
+ if (member_rids[i] == rid_array->rids[k].rid) {
+ already_member = true;
+ break;
+ }
+ }
+ if (!already_member) {
+ if (!add_rid_to_array_unique(ctx,
+ member_rids[i],
+ &add_rids, &num_add_rids)) {
+ werr = WERR_GEN_FAILURE;
+ goto done;
+ }
+ }
+ }
+
+ /* del list */
+
+ for (k=0; k < rid_array->count; k++) {
+ bool keep_member = false;
+ for (i=0; i < r->in.num_entries; i++) {
+ if (member_rids[i] == rid_array->rids[k].rid) {
+ keep_member = true;
+ break;
+ }
+ }
+ if (!keep_member) {
+ if (!add_rid_to_array_unique(ctx,
+ rid_array->rids[k].rid,
+ &del_rids, &num_del_rids)) {
+ werr = WERR_GEN_FAILURE;
+ goto done;
+ }
+ }
+ }
+
+ /* add list */
+
+ for (i=0; i < num_add_rids; i++) {
+ status = dcerpc_samr_OpenGroup(b, talloc_tos(),
+ &domain_handle,
+ SAMR_GROUP_ACCESS_ADD_MEMBER,
+ add_rids[i],
+ &group_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
+ &group_handle,
+ user_rids.ids[0],
+ 7 /* ? */,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (is_valid_policy_hnd(&group_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
+ }
+ }
+
+ /* del list */
+
+ for (i=0; i < num_del_rids; i++) {
+ status = dcerpc_samr_OpenGroup(b, talloc_tos(),
+ &domain_handle,
+ SAMR_GROUP_ACCESS_REMOVE_MEMBER,
+ del_rids[i],
+ &group_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
+ &group_handle,
+ user_rids.ids[0],
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (is_valid_policy_hnd(&group_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
+ }
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (is_valid_policy_hnd(&group_handle)) {
+ dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserSetGroups_l(struct libnetapi_ctx *ctx,
+ struct NetUserSetGroups *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetGroups);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS add_LOCALGROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ const char *group_name,
+ uint8_t **buffer,
+ uint32_t *num_entries)
+{
+ struct LOCALGROUP_USERS_INFO_0 u0;
+
+ switch (level) {
+ case 0:
+ u0.lgrui0_name = talloc_strdup(mem_ctx, group_name);
+ NT_STATUS_HAVE_NO_MEMORY(u0.lgrui0_name);
+
+ ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_USERS_INFO_0, u0,
+ (struct LOCALGROUP_USERS_INFO_0 **)buffer, num_entries);
+ break;
+ default:
+ return NT_STATUS_INVALID_INFO_CLASS;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx,
+ struct NetUserGetLocalGroups *r)
+{
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle, domain_handle, user_handle,
+ builtin_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct samr_Ids user_rids, name_types;
+ struct samr_RidWithAttributeArray *rid_array = NULL;
+ struct lsa_Strings names;
+ struct samr_Ids types;
+ uint32_t *rids = NULL;
+ size_t num_rids = 0;
+ struct dom_sid user_sid;
+ struct lsa_SidArray sid_array;
+ struct samr_Ids domain_rids;
+ struct samr_Ids builtin_rids;
+
+ int i;
+ uint32_t entries_read = 0;
+
+ NTSTATUS status;
+ NTSTATUS result = NT_STATUS_OK;
+ WERROR werr;
+ struct dcerpc_binding_handle *b = NULL;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ *r->out.buffer = NULL;
+ *r->out.entries_read = 0;
+ *r->out.total_entries = 0;
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ b = pipe_cli->binding_handle;
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
+ SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_LOOKUP_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
+ SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.user_name);
+
+ status = dcerpc_samr_LookupNames(b, talloc_tos(),
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &user_rids,
+ &name_types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (user_rids.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (name_types.count != 1) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ status = dcerpc_samr_OpenUser(b, talloc_tos(),
+ &domain_handle,
+ SAMR_USER_ACCESS_GET_GROUPS,
+ user_rids.ids[0],
+ &user_handle,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = dcerpc_samr_GetGroupsForUser(b, talloc_tos(),
+ &user_handle,
+ &rid_array,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!sid_compose(&user_sid, domain_sid, user_rids.ids[0])) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ sid_array.num_sids = rid_array->count + 1;
+ sid_array.sids = talloc_array(ctx, struct lsa_SidPtr, sid_array.num_sids);
+ if (!sid_array.sids) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ sid_array.sids[0].sid = dom_sid_dup(ctx, &user_sid);
+ if (!sid_array.sids[0].sid) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ for (i=0; i < rid_array->count; i++) {
+ struct dom_sid sid;
+
+ if (!sid_compose(&sid, domain_sid, rid_array->rids[i].rid)) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ sid_array.sids[i+1].sid = dom_sid_dup(ctx, &sid);
+ if (!sid_array.sids[i+1].sid) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+ }
+
+ status = dcerpc_samr_GetAliasMembership(b, talloc_tos(),
+ &domain_handle,
+ &sid_array,
+ &domain_rids,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ for (i=0; i < domain_rids.count; i++) {
+ if (!add_rid_to_array_unique(ctx, domain_rids.ids[i],
+ &rids, &num_rids)) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+ }
+
+ status = dcerpc_samr_GetAliasMembership(b, talloc_tos(),
+ &builtin_handle,
+ &sid_array,
+ &builtin_rids,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ for (i=0; i < builtin_rids.count; i++) {
+ if (!add_rid_to_array_unique(ctx, builtin_rids.ids[i],
+ &rids, &num_rids)) {
+ werr = WERR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+ }
+
+ status = dcerpc_samr_LookupRids(b, talloc_tos(),
+ &builtin_handle,
+ num_rids,
+ rids,
+ &names,
+ &types,
+ &result);
+ if (any_nt_status_not_ok(status, result, &status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ if (names.count != num_rids) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+ if (types.count != num_rids) {
+ werr = WERR_BAD_NET_RESP;
+ goto done;
+ }
+
+ for (i=0; i < names.count; i++) {
+ status = add_LOCALGROUP_USERS_INFO_X_buffer(ctx,
+ r->in.level,
+ names.names[i].string,
+ r->out.buffer,
+ &entries_read);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ *r->out.entries_read = entries_read;
+ *r->out.total_entries = entries_read;
+
+ done:
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserGetLocalGroups_l(struct libnetapi_ctx *ctx,
+ struct NetUserGetLocalGroups *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetLocalGroups);
+}
diff --git a/source3/lib/netapi/wkstainfo.c b/source3/lib/netapi/wkstainfo.c
new file mode 100644
index 0000000..9cfcff4
--- /dev/null
+++ b/source3/lib/netapi/wkstainfo.c
@@ -0,0 +1,154 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Workstation Support
+ * Copyright (C) Guenther Deschner 2007
+ * Copyright (C) Hans Leidekker 2013
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+#include "../librpc/gen_ndr/ndr_wkssvc_c.h"
+#include "lib/smbconf/smbconf.h"
+#include "lib/smbconf/smbconf_reg.h"
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetWkstaGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetWkstaGetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetWkstaGetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS map_wksta_info_to_WKSTA_INFO_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ union wkssvc_NetWkstaInfo *i,
+ uint8_t **buffer)
+{
+ struct WKSTA_INFO_100 i100;
+ struct WKSTA_INFO_101 i101;
+ struct WKSTA_INFO_102 i102;
+ uint32_t num_info = 0;
+
+ switch (level) {
+ case 100:
+ i100.wki100_platform_id = i->info100->platform_id;
+ i100.wki100_computername = talloc_strdup(mem_ctx, i->info100->server_name);
+ i100.wki100_langroup = talloc_strdup(mem_ctx, i->info100->domain_name);
+ i100.wki100_ver_major = i->info100->version_major;
+ i100.wki100_ver_minor = i->info100->version_minor;
+
+ ADD_TO_ARRAY(mem_ctx, struct WKSTA_INFO_100, i100,
+ (struct WKSTA_INFO_100 **)buffer,
+ &num_info);
+ break;
+
+ case 101:
+ i101.wki101_platform_id = i->info101->platform_id;
+ i101.wki101_computername = talloc_strdup(mem_ctx, i->info101->server_name);
+ i101.wki101_langroup = talloc_strdup(mem_ctx, i->info101->domain_name);
+ i101.wki101_ver_major = i->info101->version_major;
+ i101.wki101_ver_minor = i->info101->version_minor;
+ i101.wki101_lanroot = talloc_strdup(mem_ctx, i->info101->lan_root);
+
+ ADD_TO_ARRAY(mem_ctx, struct WKSTA_INFO_101, i101,
+ (struct WKSTA_INFO_101 **)buffer,
+ &num_info);
+ break;
+
+ case 102:
+ i102.wki102_platform_id = i->info102->platform_id;
+ i102.wki102_computername = talloc_strdup(mem_ctx, i->info102->server_name);
+ i102.wki102_langroup = talloc_strdup(mem_ctx, i->info102->domain_name);
+ i102.wki102_ver_major = i->info102->version_major;
+ i102.wki102_ver_minor = i->info102->version_minor;
+ i102.wki102_lanroot = talloc_strdup(mem_ctx, i->info102->lan_root);
+ i102.wki102_logged_on_users = i->info102->logged_on_users;
+
+ ADD_TO_ARRAY(mem_ctx, struct WKSTA_INFO_102, i102,
+ (struct WKSTA_INFO_102 **)buffer,
+ &num_info);
+ break;
+
+ default:
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetWkstaGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetWkstaGetInfo *r)
+{
+ NTSTATUS status;
+ WERROR werr;
+ union wkssvc_NetWkstaInfo info;
+ struct dcerpc_binding_handle *b;
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ switch (r->in.level) {
+ case 100:
+ case 101:
+ case 102:
+ break;
+ default:
+ return WERR_INVALID_LEVEL;
+ }
+
+ werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
+ &ndr_table_wkssvc,
+ &b);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = dcerpc_wkssvc_NetWkstaGetInfo(b, talloc_tos(),
+ r->in.server_name,
+ r->in.level,
+ &info,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = map_wksta_info_to_WKSTA_INFO_buffer(ctx, r->in.level, &info,
+ r->out.buffer);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ return werr;
+}