mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
r24667: Finally merge the registry improvements that Wilco Baan Hofman and I have
been working on for at least half a year now. Contains the following
improvements:
* proper layering (finally!) for the registry library. Distinction is
now made between 'real' backends (local, remote, wine, etc) and
the low-level hive backends (regf, creg, ldb, ...) that are only used
by the local registry backend
* tests for all important hive and registry operations
* re-enable RPC-WINREG tests (still needs more work though, as
some return values aren't checked yet)
* write support for REGF files
* dir backend now supports setting/reading values, creating keys
* support for storing security descriptors
* remove CREG backend as it was incomplete, didn't match the data model
and wasn't used at all anyway
* support for parsing ADM files as used by the policy editor (see lib/policy)
* support for parsing PREG files (format used by .POL files)
* new streaming interface for registry diffs (improves speed and memory usage
for regdiff/regpatch significantly)
... and fixes a large number of bugs in the registry code
(This used to be commit 7a1eec6358
)
This commit is contained in:
parent
8e789517b7
commit
b409d4120f
16
.bzrignore
16
.bzrignore
@ -143,9 +143,19 @@ source/smbd/pidfile.h
|
||||
source/torture/rap/proto.h
|
||||
*_asn1.h
|
||||
*_asn1_files
|
||||
*_err.c
|
||||
*_proto.h
|
||||
source/heimdal/lib/hx509/asn1_*.c
|
||||
*_err.h
|
||||
*_err.c
|
||||
source/smbd/pidfile.h
|
||||
source/ntvfs/cifs_posix_cli/proto.h
|
||||
source/lib/util/util_tdb.h
|
||||
source/lib/cmdline/popt_credentials.h
|
||||
source/lib/policy/lex.c
|
||||
source/lib/policy/parse_adm.c
|
||||
source/lib/policy/parse_adm.h
|
||||
source/heimdal/lib/roken/err.h
|
||||
source/kdc/pac_glue.h
|
||||
source/scripting/ejs/ejsnet/proto.h
|
||||
source/heimdal/lib/hx509/asn1_*.c
|
||||
*.gcno
|
||||
@ -160,6 +170,7 @@ source/coverage
|
||||
source/st
|
||||
source/samba.info
|
||||
source/pidl/cover_db
|
||||
source/lib/registry/apidocs
|
||||
source/dsdb/repl/drepl_service_proto.h
|
||||
webapps/qooxdoo-0.6.5-sdk/frontend/framework/.cache
|
||||
webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/data
|
||||
@ -169,6 +180,7 @@ webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/locale/translation
|
||||
webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/translation/messages.pot
|
||||
source/torture/ndr/proto.h
|
||||
source/bin/modules/*
|
||||
source/lib/registry/API
|
||||
source/tests
|
||||
source/torture/unix/proto.h
|
||||
source/lib/tdb/bin/tdbtool
|
||||
@ -182,3 +194,5 @@ source/lib/ldb/examples/ldbreader
|
||||
source/lib/ldb/examples/ldifreader
|
||||
source/lib/tdb/bin/tdbbackup
|
||||
source/lib/tdb/bin/tdbdump
|
||||
source/lib/registry/tools/common.h
|
||||
source/librpc/ndr/ndr_table.h
|
||||
|
5
BRANCH.TODO
Normal file
5
BRANCH.TODO
Normal file
@ -0,0 +1,5 @@
|
||||
The following things still need to be fixed before this branch
|
||||
can be merged:
|
||||
- RPC-WINREG
|
||||
- tests for diff functionality
|
||||
- test for classname and last_mod_time being kept
|
@ -5,6 +5,7 @@ include charset/config.mk
|
||||
include ldb/config.mk
|
||||
include tls/config.mk
|
||||
include registry/config.mk
|
||||
include policy/config.mk
|
||||
include messaging/config.mk
|
||||
include events/config.mk
|
||||
include cmdline/config.mk
|
||||
|
48
source4/lib/policy/adm.h
Normal file
48
source4/lib/policy/adm.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Copyright (C) 2006 Wilco Baan Hofman <wilco@baanhofman.nl>
|
||||
Copyright (C) 2006 Jelmer Vernooij <jelmer@samba.org>
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ADM_H__
|
||||
#define __ADM_H__
|
||||
|
||||
struct adm_file {
|
||||
struct adm_class *classes;
|
||||
};
|
||||
|
||||
struct adm_class {
|
||||
struct adm_category *categories;
|
||||
};
|
||||
|
||||
struct adm_category {
|
||||
struct adm_category *subcategories;
|
||||
struct adm_policy *policies;
|
||||
};
|
||||
|
||||
struct adm_policy {
|
||||
struct adm_part *parts;
|
||||
|
||||
};
|
||||
|
||||
struct adm_part {
|
||||
|
||||
};
|
||||
|
||||
struct adm_file *adm_read_file(const char *);
|
||||
|
||||
#endif /* __ADM_H__ */
|
12
source4/lib/policy/config.mk
Normal file
12
source4/lib/policy/config.mk
Normal file
@ -0,0 +1,12 @@
|
||||
[LIBRARY::LIBPOLICY]
|
||||
CFLAGS = -Iheimdal/lib/roken
|
||||
OBJ_FILES = lex.o parse_adm.o
|
||||
PRIVATE_DEPENDENCIES = LIBSAMBA-UTIL LIBSAMBA-CONFIG LIBTALLOC CHARSET
|
||||
|
||||
lib/policy/lex.l: lib/policy/parse_adm.h
|
||||
|
||||
lib/policy/parse_adm.h: lib/policy/parse_adm.c
|
||||
|
||||
[BINARY::dumpadm]
|
||||
OBJ_FILES = dumpadm.o
|
||||
PRIVATE_DEPENDENCIES = LIBPOLICY LIBPOPT LIBSAMBA-CONFIG LIBTALLOC LIBSAMBA-UTIL CHARSET
|
54
source4/lib/policy/dumpadm.c
Normal file
54
source4/lib/policy/dumpadm.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Copyright (C) 2006 Wilco Baan Hofman <wilco@baanhofman.nl>
|
||||
Copyright (C) 2006 Jelmer Vernooij <jelmer@samba.org>
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "lib/popt/popt.h"
|
||||
#include "lib/policy/adm.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
BOOL ret = True;
|
||||
poptContext pc;
|
||||
struct poptOption long_options[] = {
|
||||
POPT_AUTOHELP
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
pc = poptGetContext(argv[0], argc, (const char **)argv, long_options, 0);
|
||||
|
||||
poptSetOtherOptionHelp(pc, "<ADM-FILE> ...");
|
||||
|
||||
while ((poptGetNextOpt(pc) != -1))
|
||||
|
||||
if(!poptPeekArg(pc)) {
|
||||
poptPrintUsage(pc, stderr, 0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (poptPeekArg(pc)) {
|
||||
const char *name = poptGetArg(pc);
|
||||
|
||||
adm_read_file(name);
|
||||
}
|
||||
|
||||
poptFreeContext(pc);
|
||||
|
||||
return ret;
|
||||
}
|
142
source4/lib/policy/lex.l
Normal file
142
source4/lib/policy/lex.l
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Copyright (C) 2006 Wilco Baan Hofman <wilco@baanhofman.nl>
|
||||
Copyright (C) 2006 Jelmer Vernooij <jelmer@samba.org>
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
%{
|
||||
#include "includes.h"
|
||||
#include "lib/policy/parse_adm.h"
|
||||
void error_message (const char *format, ...);
|
||||
int yyparse (void);
|
||||
|
||||
static int lineno = 1;
|
||||
static bool utf16 = false;
|
||||
|
||||
#define YY_INPUT(buf,result,max_size) \
|
||||
{ \
|
||||
if (utf16) { \
|
||||
uint16_t v; \
|
||||
if (fread(&v, 2, 1, yyin) < 1) \
|
||||
result = YY_NULL; \
|
||||
else \
|
||||
result = push_codepoint(buf, v); \
|
||||
} else { \
|
||||
int c = getc(yyin); \
|
||||
result = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \
|
||||
} \
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%%
|
||||
|
||||
ACTIONLIST { return ACTIONLIST; }
|
||||
CATEGORY { return CATEGORY; }
|
||||
CHECKBOX { return CHECKBOX; }
|
||||
CLASS { return CLASS; }
|
||||
DELETE { return DEL; }
|
||||
DEFAULT { return DEFAULT; }
|
||||
DROPDOWNLIST { return DROPDOWNLIST; }
|
||||
EDITTEXT { return EDITTEXT; }
|
||||
END { return END; }
|
||||
EXPLAIN { return EXPLAIN; }
|
||||
ITEMLIST { return ITEMLIST; }
|
||||
KEYNAME { return KEYNAME; }
|
||||
MACHINE { return MACHINE; }
|
||||
MIN { return MINIMUM; }
|
||||
MAX { return MAXIMUM; }
|
||||
NAME { return NAME; }
|
||||
NUMERIC { return NUMERIC; }
|
||||
PART { return PART; }
|
||||
POLICY { return POLICY; }
|
||||
REQUIRED { return REQUIRED; }
|
||||
SPIN { return SPIN; }
|
||||
SUPPORTED { return SUPPORTED; }
|
||||
TEXT { return TEXT; }
|
||||
USER { return USER; }
|
||||
VALUE { return VALUE; }
|
||||
VALUENAME { return VALUENAME; }
|
||||
VALUEON { return VALUEON; }
|
||||
VALUEOFF { return VALUEOFF; }
|
||||
= { return EQUALS; }
|
||||
\[strings\] { return STRINGSSECTION; }
|
||||
|
||||
[0-9]+ {
|
||||
char *e, *y = yytext;
|
||||
yylval.integer = strtol((const char *)yytext, &e, 0);
|
||||
if(e == y)
|
||||
error_message("malformed constant (%s)", yytext);
|
||||
else
|
||||
return INTEGER;
|
||||
}
|
||||
|
||||
[A-Za-z\\{}][{}\-\\A-Za-z0-9_]* {
|
||||
yylval.text = strdup ((const char *)yytext);
|
||||
return LITERAL;
|
||||
}
|
||||
|
||||
"!!"[A-Za-z][-A-Za-z0-9_]* {
|
||||
yylval.text = strdup ((const char *)yytext);
|
||||
return LOOKUPLITERAL;
|
||||
}
|
||||
[ \t]+
|
||||
\n { lineno++; }
|
||||
;[^\n]*\n { lineno++; }
|
||||
\"([^\n]+)\n { lineno++; yylval.text = strdup((const char *)yytext); return LITERAL; }
|
||||
%%
|
||||
|
||||
#ifndef yywrap /* XXX */
|
||||
int
|
||||
yywrap ()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
error_message (const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
fprintf (stderr, "%d:", lineno);
|
||||
vfprintf (stderr, format, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
struct adm_file *adm_read_file(const char *file)
|
||||
{
|
||||
uint8_t c[2];
|
||||
yyin = fopen(file, "r");
|
||||
if (yyin == NULL)
|
||||
return NULL;
|
||||
|
||||
c[0] = getc(yyin);
|
||||
c[1] = getc(yyin);
|
||||
if (c[0] == 0xff && c[1] == 0xfe) {
|
||||
utf16 = true;
|
||||
} else {
|
||||
rewind(yyin);
|
||||
}
|
||||
|
||||
yyparse();
|
||||
|
||||
return NULL; /* FIXME */
|
||||
}
|
138
source4/lib/policy/parse_adm.y
Normal file
138
source4/lib/policy/parse_adm.y
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Copyright (C) 2006 Wilco Baan Hofman <wilco@baanhofman.nl>
|
||||
Copyright (C) 2006 Jelmer Vernooij <jelmer@samba.org>
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
For more information on the .ADM file format:
|
||||
http://msdn2.microsoft.com/en-us/library/aa372405.aspx
|
||||
*/
|
||||
|
||||
%{
|
||||
#include "config.h"
|
||||
void error_message (const char *format, ...);
|
||||
int yyparse (void);
|
||||
void yyerror (const char *s);
|
||||
extern int yylex (void);
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
char *text;
|
||||
int integer;
|
||||
}
|
||||
|
||||
%token CATEGORY
|
||||
%token CLASS
|
||||
%token USER
|
||||
%token MACHINE
|
||||
%token POLICY
|
||||
%token KEYNAME
|
||||
%token EXPLAIN
|
||||
%token VALUENAME
|
||||
%token VALUEON VALUEOFF
|
||||
%token PART
|
||||
%token ITEMLIST
|
||||
%token NAME
|
||||
%token VALUE
|
||||
%token NUMERIC EDITTEXT TEXT DROPDOWNLIST CHECKBOX
|
||||
%token MINIMUM MAXIMUM DEFAULT
|
||||
%token END
|
||||
%token ACTIONLIST
|
||||
%token DEL
|
||||
%token SUPPORTED
|
||||
%token <text> LITERAL
|
||||
%token <integer> INTEGER
|
||||
%token <text> LOOKUPLITERAL
|
||||
%token CLIENTEXT
|
||||
%token REQUIRED
|
||||
%token NOSORT
|
||||
%token SPIN
|
||||
%token EQUALS
|
||||
%token STRINGSSECTION
|
||||
|
||||
%start admfile
|
||||
|
||||
%%
|
||||
|
||||
admfile: classes strings;
|
||||
|
||||
classes: /* empty */ | class classes;
|
||||
|
||||
class: CLASS classvalue categories;
|
||||
classvalue: USER|MACHINE;
|
||||
|
||||
categories: /* empty */ | category categories;
|
||||
|
||||
string: LITERAL | LOOKUPLITERAL;
|
||||
|
||||
category: CATEGORY string categoryitems END CATEGORY;
|
||||
|
||||
categoryitem: explain | category | policy | keyname;
|
||||
categoryitems: categoryitem categoryitems | /* empty */ ;
|
||||
|
||||
policy: POLICY string policyitems END POLICY;
|
||||
policyitem: explain | keyname | valuename | valueon | valueoff | min | max | defaultvalue | supported | part;
|
||||
policyitems: policyitem policyitems | /* empty */;
|
||||
|
||||
valuetype: NUMERIC | EDITTEXT | TEXT | DROPDOWNLIST | CHECKBOX;
|
||||
|
||||
part: PART string valuetype partitems END PART;
|
||||
|
||||
spin: SPIN INTEGER;
|
||||
|
||||
partitem: keyname | valuename | valueon | valueoff | min | max | defaultvalue | itemlist | REQUIRED | spin;
|
||||
partitems: partitem partitems | /* empty */;
|
||||
|
||||
min: MINIMUM INTEGER;
|
||||
max: MAXIMUM INTEGER;
|
||||
defaultvalue: DEFAULT INTEGER;
|
||||
|
||||
explain: EXPLAIN string;
|
||||
value: DEL | NUMERIC INTEGER;
|
||||
|
||||
valueon: VALUEON value;
|
||||
valueoff: VALUEOFF value;
|
||||
|
||||
valuename: VALUENAME string;
|
||||
keyname: KEYNAME string;
|
||||
|
||||
itemlist: ITEMLIST items END ITEMLIST;
|
||||
itemname: NAME string;
|
||||
itemvalue: VALUE value;
|
||||
|
||||
item: itemname | itemvalue | DEFAULT | actionlist;
|
||||
items: /* empty */ | item items;
|
||||
|
||||
supported: SUPPORTED string;
|
||||
|
||||
actionlist: ACTIONLIST actions END ACTIONLIST;
|
||||
actions: valuename actions | itemvalue actions | /* empty */;
|
||||
|
||||
variable: LITERAL EQUALS LITERAL;
|
||||
variables: variable variables | /* empty */;
|
||||
strings: STRINGSSECTION variables;
|
||||
|
||||
%%
|
||||
|
||||
void
|
||||
yyerror (const char *s)
|
||||
{
|
||||
error_message ("%s\n", s);
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,7 +15,7 @@ WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
INPUT = . common
|
||||
INPUT = .
|
||||
FILE_PATTERNS = *.c *.h *.dox
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
|
@ -1,30 +1,31 @@
|
||||
This is the registry library. The registry is basically a bunch of
|
||||
hives that can be loaded from different places.
|
||||
hives, each of which is loaded from a file. When using a local registry,
|
||||
it is possible to specify where hives should be loaded from, etc.
|
||||
|
||||
The various registry backends provide support for loading/saving
|
||||
specific types of hives:
|
||||
There are separate APIs for accessing the data in a hive and the
|
||||
data in the registry itself. Each supports different backends.
|
||||
|
||||
The following "full registry" backends are currently provided:
|
||||
|
||||
* Remote (over DCE/RPC)
|
||||
* Local (allows "mounting" hives)
|
||||
* Wine (uses the wine plain-text file)
|
||||
|
||||
The following hive backends are supported:
|
||||
|
||||
- ldb
|
||||
- w95 (USER.DAT-style files)
|
||||
- nt4 (NTUSER.DAT-style files)
|
||||
- gconf (GNOME configuration)
|
||||
- regf (NTUSER.DAT-style files)
|
||||
- rpc (Remote individual hives)
|
||||
- directory
|
||||
|
||||
Instead of opening individual hives, one can also open a 'complete'
|
||||
registry by using one of these three functions:
|
||||
|
||||
- reg_open_local() - load local registry, see below
|
||||
- reg_open_remote() - connect to remote registry over RPC
|
||||
- reg_open_wine() (not working yet)
|
||||
|
||||
reg_open_local() loads a set of hives based on smb.conf settings.
|
||||
reg_open_samba() loads a set of hives based on smb.conf settings.
|
||||
Lines in smb.conf should have the following syntax:
|
||||
|
||||
registry:<hivename> = <backend>:<location>
|
||||
|
||||
So an example usage could be:
|
||||
|
||||
registry:HKEY_CURRENT_USER = nt4:NTUSER.DAT
|
||||
registry:HKEY_CURRENT_USER = regf:NTUSER.DAT
|
||||
registry:HKEY_LOCAL_MACHINE = ldb:tdb://registry.tdb
|
||||
|
||||
WERR_NOT_SUPPORTED will be returned for all hives that haven't been set.
|
||||
|
@ -4,10 +4,10 @@
|
||||
reg_backend_dir:
|
||||
- value support
|
||||
|
||||
reg_backend_w95.c:
|
||||
reg_backend_creg.c:
|
||||
- write support
|
||||
|
||||
reg_backend_nt4:
|
||||
reg_backend_regf:
|
||||
- write support
|
||||
|
||||
reg_backend_rpc:
|
||||
|
@ -1,584 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Transparent registry backend handling
|
||||
Copyright (C) Jelmer Vernooij 2003-2004.
|
||||
|
||||
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/util/dlinklist.h"
|
||||
#include "lib/registry/registry.h"
|
||||
#include "build.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Main registry functions
|
||||
*/
|
||||
|
||||
/* List of available backends */
|
||||
static struct reg_init_function_entry *backends = NULL;
|
||||
|
||||
static struct reg_init_function_entry *reg_find_backend_entry(const char *name);
|
||||
|
||||
/** Register a new backend. */
|
||||
_PUBLIC_ NTSTATUS registry_register(const void *_hive_ops)
|
||||
{
|
||||
const struct hive_operations *hive_ops = _hive_ops;
|
||||
struct reg_init_function_entry *entry = backends;
|
||||
|
||||
DEBUG(5,("Attempting to register registry backend %s\n", hive_ops->name));
|
||||
|
||||
/* Check for duplicates */
|
||||
if (reg_find_backend_entry(hive_ops->name)) {
|
||||
DEBUG(0,("There already is a registry backend registered with the name %s!\n", hive_ops->name));
|
||||
return NT_STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
|
||||
entry = talloc(talloc_autofree_context(), struct reg_init_function_entry);
|
||||
entry->hive_functions = hive_ops;
|
||||
|
||||
DLIST_ADD(backends, entry);
|
||||
DEBUG(5,("Successfully added registry backend '%s'\n", hive_ops->name));
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/** Find a backend in the list of available backends */
|
||||
static struct reg_init_function_entry *reg_find_backend_entry(const char *name)
|
||||
{
|
||||
struct reg_init_function_entry *entry;
|
||||
|
||||
entry = backends;
|
||||
|
||||
while(entry) {
|
||||
if (strcmp(entry->hive_functions->name, name) == 0) return entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Initialize the registry subsystem */
|
||||
_PUBLIC_ NTSTATUS registry_init(void)
|
||||
{
|
||||
init_module_fn static_init[] = STATIC_registry_MODULES;
|
||||
init_module_fn *shared_init = load_samba_modules(NULL, "registry");
|
||||
|
||||
run_init_functions(static_init);
|
||||
run_init_functions(shared_init);
|
||||
|
||||
talloc_free(shared_init);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/** Check whether a certain backend is present. */
|
||||
_PUBLIC_ BOOL reg_has_backend(const char *backend)
|
||||
{
|
||||
return reg_find_backend_entry(backend) != NULL?True:False;
|
||||
}
|
||||
|
||||
const struct reg_predefined_key reg_predefined_keys[] = {
|
||||
{HKEY_CLASSES_ROOT,"HKEY_CLASSES_ROOT" },
|
||||
{HKEY_CURRENT_USER,"HKEY_CURRENT_USER" },
|
||||
{HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE" },
|
||||
{HKEY_PERFORMANCE_DATA, "HKEY_PERFORMANCE_DATA" },
|
||||
{HKEY_USERS, "HKEY_USERS" },
|
||||
{HKEY_CURRENT_CONFIG, "HKEY_CURRENT_CONFIG" },
|
||||
{HKEY_DYN_DATA, "HKEY_DYN_DATA" },
|
||||
{HKEY_PERFORMANCE_TEXT, "HKEY_PERFORMANCE_TEXT" },
|
||||
{HKEY_PERFORMANCE_NLSTEXT, "HKEY_PERFORMANCE_NLSTEXT" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/** Obtain a list of predefined keys. */
|
||||
_PUBLIC_ int reg_list_predefs(TALLOC_CTX *mem_ctx, char ***predefs, uint32_t **hkeys)
|
||||
{
|
||||
int i;
|
||||
*predefs = talloc_array(mem_ctx, char *, ARRAY_SIZE(reg_predefined_keys));
|
||||
*hkeys = talloc_array(mem_ctx, uint32_t, ARRAY_SIZE(reg_predefined_keys));
|
||||
|
||||
for (i = 0; reg_predefined_keys[i].name; i++) {
|
||||
(*predefs)[i] = talloc_strdup(mem_ctx, reg_predefined_keys[i].name);
|
||||
(*hkeys)[i] = reg_predefined_keys[i].handle;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/** Obtain name of specific hkey. */
|
||||
_PUBLIC_ const char *reg_get_predef_name(uint32_t hkey)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; reg_predefined_keys[i].name; i++) {
|
||||
if (reg_predefined_keys[i].handle == hkey) return reg_predefined_keys[i].name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Get predefined key by name. */
|
||||
_PUBLIC_ WERROR reg_get_predefined_key_by_name(struct registry_context *ctx, const char *name, struct registry_key **key)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; reg_predefined_keys[i].name; i++) {
|
||||
if (!strcasecmp(reg_predefined_keys[i].name, name)) return reg_get_predefined_key(ctx, reg_predefined_keys[i].handle, key);
|
||||
}
|
||||
|
||||
DEBUG(1, ("No predefined key with name '%s'\n", name));
|
||||
|
||||
return WERR_BADFILE;
|
||||
}
|
||||
|
||||
/** Get predefined key by id. */
|
||||
_PUBLIC_ WERROR reg_get_predefined_key(struct registry_context *ctx, uint32_t hkey, struct registry_key **key)
|
||||
{
|
||||
WERROR ret = ctx->get_predefined_key(ctx, hkey, key);
|
||||
|
||||
if (W_ERROR_IS_OK(ret)) {
|
||||
(*key)->name = talloc_strdup(*key, reg_get_predef_name(hkey));
|
||||
(*key)->path = "";
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Open a registry file/host/etc */
|
||||
_PUBLIC_ WERROR reg_open_hive(TALLOC_CTX *parent_ctx, const char *backend, const char *location, struct auth_session_info *session_info, struct cli_credentials *credentials, struct registry_key **root)
|
||||
{
|
||||
struct registry_hive *rethive;
|
||||
struct registry_key *retkey = NULL;
|
||||
struct reg_init_function_entry *entry;
|
||||
WERROR werr;
|
||||
|
||||
entry = reg_find_backend_entry(backend);
|
||||
|
||||
if (!entry) {
|
||||
DEBUG(0, ("No such registry backend '%s' loaded!\n", backend));
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
if(!entry->hive_functions || !entry->hive_functions->open_hive) {
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
rethive = talloc(parent_ctx, struct registry_hive);
|
||||
rethive->location = location?talloc_strdup(rethive, location):NULL;
|
||||
rethive->session_info = talloc_reference(rethive, session_info);
|
||||
rethive->credentials = talloc_reference(rethive, credentials);
|
||||
rethive->functions = entry->hive_functions;
|
||||
rethive->backend_data = NULL;
|
||||
|
||||
werr = entry->hive_functions->open_hive(rethive, &retkey);
|
||||
|
||||
if(!W_ERROR_IS_OK(werr)) {
|
||||
return werr;
|
||||
}
|
||||
|
||||
if(!retkey) {
|
||||
DEBUG(0, ("Backend %s didn't provide root key!\n", backend));
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
rethive->root = retkey;
|
||||
|
||||
retkey->hive = rethive;
|
||||
retkey->name = NULL;
|
||||
retkey->path = talloc_strdup(retkey, "");
|
||||
|
||||
*root = retkey;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a key
|
||||
* First tries to use the open_key function from the backend
|
||||
* then falls back to get_subkey_by_name and later get_subkey_by_index
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, struct registry_key **result)
|
||||
{
|
||||
WERROR error;
|
||||
|
||||
if(!parent) {
|
||||
DEBUG(0, ("Invalid parent key specified for open of '%s'\n", name));
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if(!parent->hive->functions->open_key &&
|
||||
(parent->hive->functions->get_subkey_by_name ||
|
||||
parent->hive->functions->get_subkey_by_index)) {
|
||||
char *orig = strdup(name),
|
||||
*curbegin = orig,
|
||||
*curend = strchr(orig, '\\');
|
||||
struct registry_key *curkey = parent;
|
||||
|
||||
while(curbegin && *curbegin) {
|
||||
if(curend)*curend = '\0';
|
||||
error = reg_key_get_subkey_by_name(mem_ctx, curkey, curbegin, &curkey);
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
SAFE_FREE(orig);
|
||||
return error;
|
||||
}
|
||||
if(!curend) break;
|
||||
curbegin = curend + 1;
|
||||
curend = strchr(curbegin, '\\');
|
||||
}
|
||||
SAFE_FREE(orig);
|
||||
|
||||
*result = curkey;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
if(!parent->hive->functions->open_key) {
|
||||
DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n"));
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
error = parent->hive->functions->open_key(mem_ctx, parent, name, result);
|
||||
|
||||
if(!W_ERROR_IS_OK(error)) return error;
|
||||
|
||||
(*result)->hive = parent->hive;
|
||||
(*result)->path = ((parent->hive->root == parent)?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name));
|
||||
(*result)->hive = parent->hive;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value by index
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *key, int idx, struct registry_value **val)
|
||||
{
|
||||
if(!key) return WERR_INVALID_PARAM;
|
||||
|
||||
if(key->hive->functions->get_value_by_index) {
|
||||
WERROR status = key->hive->functions->get_value_by_index(mem_ctx, key, idx, val);
|
||||
if(!W_ERROR_IS_OK(status))
|
||||
return status;
|
||||
} else {
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of subkeys.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_num_subkeys(const struct registry_key *key, uint32_t *count)
|
||||
{
|
||||
if(!key) return WERR_INVALID_PARAM;
|
||||
|
||||
if(key->hive->functions->num_subkeys) {
|
||||
return key->hive->functions->num_subkeys(key, count);
|
||||
}
|
||||
|
||||
if(key->hive->functions->get_subkey_by_index) {
|
||||
int i;
|
||||
WERROR error;
|
||||
struct registry_key *dest = NULL;
|
||||
TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
|
||||
|
||||
for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, key, i, &dest)); i++);
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
*count = i;
|
||||
if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK;
|
||||
return error;
|
||||
}
|
||||
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of values of a key.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_num_values(const struct registry_key *key, uint32_t *count)
|
||||
{
|
||||
|
||||
if(!key) return WERR_INVALID_PARAM;
|
||||
|
||||
if (key->hive->functions->num_values) {
|
||||
return key->hive->functions->num_values(key, count);
|
||||
}
|
||||
|
||||
if(key->hive->functions->get_value_by_index) {
|
||||
int i;
|
||||
WERROR error;
|
||||
struct registry_value *dest;
|
||||
TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
|
||||
|
||||
for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_value_by_index(mem_ctx, key, i, &dest)); i++);
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
*count = i;
|
||||
if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK;
|
||||
return error;
|
||||
}
|
||||
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subkey by index.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *key, int idx, struct registry_key **subkey)
|
||||
{
|
||||
if(!key) return WERR_INVALID_PARAM;
|
||||
|
||||
if(key->hive->functions->get_subkey_by_index) {
|
||||
WERROR status = key->hive->functions->get_subkey_by_index(mem_ctx, key, idx, subkey);
|
||||
if(!NT_STATUS_IS_OK(status)) return status;
|
||||
} else {
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if(key->hive->root == key)
|
||||
(*subkey)->path = talloc_strdup(mem_ctx, (*subkey)->name);
|
||||
else
|
||||
(*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
|
||||
|
||||
(*subkey)->hive = key->hive;
|
||||
return WERR_OK;;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subkey by name.
|
||||
*/
|
||||
WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, const struct registry_key *key, const char *name, struct registry_key **subkey)
|
||||
{
|
||||
int i;
|
||||
WERROR error = WERR_OK;
|
||||
|
||||
if(!key) return WERR_INVALID_PARAM;
|
||||
|
||||
if(key->hive->functions->get_subkey_by_name) {
|
||||
error = key->hive->functions->get_subkey_by_name(mem_ctx, key,name,subkey);
|
||||
} else if(key->hive->functions->open_key) {
|
||||
error = key->hive->functions->open_key(mem_ctx, key, name, subkey);
|
||||
} else if(key->hive->functions->get_subkey_by_index) {
|
||||
for(i = 0; W_ERROR_IS_OK(error); i++) {
|
||||
error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey);
|
||||
if(W_ERROR_IS_OK(error) && !strcasecmp((*subkey)->name, name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
|
||||
error = WERR_DEST_NOT_FOUND;
|
||||
} else {
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(error)) return error;
|
||||
|
||||
(*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
|
||||
(*subkey)->hive = key->hive;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value by name.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, const struct registry_key *key, const char *name, struct registry_value **val)
|
||||
{
|
||||
int i;
|
||||
WERROR error = WERR_OK;
|
||||
|
||||
if(!key) return WERR_INVALID_PARAM;
|
||||
|
||||
if(key->hive->functions->get_value_by_name) {
|
||||
error = key->hive->functions->get_value_by_name(mem_ctx, key,name, val);
|
||||
} else {
|
||||
for(i = 0; W_ERROR_IS_OK(error); i++) {
|
||||
error = reg_key_get_value_by_index(mem_ctx, key, i, val);
|
||||
if(W_ERROR_IS_OK(error) && !strcasecmp((*val)->name, name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
|
||||
return WERR_DEST_NOT_FOUND;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a key.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_del(struct registry_key *parent, const char *name)
|
||||
{
|
||||
WERROR error;
|
||||
if(!parent) return WERR_INVALID_PARAM;
|
||||
|
||||
|
||||
if(!parent->hive->functions->del_key)
|
||||
return WERR_NOT_SUPPORTED;
|
||||
|
||||
error = parent->hive->functions->del_key(parent, name);
|
||||
if(!W_ERROR_IS_OK(error)) return error;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a key.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **newkey)
|
||||
{
|
||||
WERROR error;
|
||||
|
||||
if (!parent) return WERR_INVALID_PARAM;
|
||||
|
||||
if (!parent->hive->functions->add_key) {
|
||||
DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->hive->functions->name));
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
error = parent->hive->functions->add_key(mem_ctx, parent, name, access_mask, desc, newkey);
|
||||
|
||||
if(!W_ERROR_IS_OK(error)) return error;
|
||||
|
||||
if (!*newkey) {
|
||||
DEBUG(0, ("Backend returned WERR_OK, but didn't specify key!\n"));
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
(*newkey)->hive = parent->hive;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_val_set(struct registry_key *key, const char *value, uint32_t type, DATA_BLOB data)
|
||||
{
|
||||
/* A 'real' set function has preference */
|
||||
if (key->hive->functions->set_value)
|
||||
return key->hive->functions->set_value(key, value, type, data);
|
||||
|
||||
DEBUG(1, ("Backend '%s' doesn't support method set_value\n", key->hive->functions->name));
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the security descriptor on a key.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_get_sec_desc(TALLOC_CTX *ctx, const struct registry_key *key, struct security_descriptor **secdesc)
|
||||
{
|
||||
/* A 'real' set function has preference */
|
||||
if (key->hive->functions->key_get_sec_desc)
|
||||
return key->hive->functions->key_get_sec_desc(ctx, key, secdesc);
|
||||
|
||||
DEBUG(1, ("Backend '%s' doesn't support method get_sec_desc\n", key->hive->functions->name));
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a value.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_del_value(const struct registry_key *key, const char *valname)
|
||||
{
|
||||
WERROR ret = WERR_OK;
|
||||
if(!key->hive->functions->del_value)
|
||||
return WERR_NOT_SUPPORTED;
|
||||
|
||||
ret = key->hive->functions->del_value(key, valname);
|
||||
|
||||
if(!W_ERROR_IS_OK(ret)) return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush a key to disk.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_flush(const struct registry_key *key)
|
||||
{
|
||||
if (!key) {
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (key->hive->functions->flush_key) {
|
||||
return key->hive->functions->flush_key(key);
|
||||
}
|
||||
|
||||
/* No need for flushing, apparently */
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum name and data lengths of the subkeys.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_subkeysizes(const struct registry_key *key, uint32_t *max_subkeylen, uint32_t *max_subkeysize)
|
||||
{
|
||||
int i = 0;
|
||||
struct registry_key *subkey;
|
||||
WERROR error;
|
||||
TALLOC_CTX *mem_ctx = talloc_init("subkeysize");
|
||||
|
||||
*max_subkeylen = *max_subkeysize = 0;
|
||||
|
||||
do {
|
||||
error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey);
|
||||
|
||||
if (W_ERROR_IS_OK(error)) {
|
||||
*max_subkeysize = MAX(*max_subkeysize, 0xFF);
|
||||
*max_subkeylen = MAX(*max_subkeylen, strlen(subkey->name));
|
||||
}
|
||||
|
||||
i++;
|
||||
} while (W_ERROR_IS_OK(error));
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum name and data lengths of the values.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_valuesizes(const struct registry_key *key, uint32_t *max_valnamelen, uint32_t *max_valbufsize)
|
||||
{
|
||||
int i = 0;
|
||||
struct registry_value *value;
|
||||
WERROR error;
|
||||
TALLOC_CTX *mem_ctx = talloc_init("subkeysize");
|
||||
|
||||
*max_valnamelen = *max_valbufsize = 0;
|
||||
|
||||
do {
|
||||
error = reg_key_get_value_by_index(mem_ctx, key, i, &value);
|
||||
|
||||
if (W_ERROR_IS_OK(error)) {
|
||||
if (value->name) {
|
||||
*max_valnamelen = MAX(*max_valnamelen, strlen(value->name));
|
||||
}
|
||||
*max_valbufsize = MAX(*max_valbufsize, value->data.length);
|
||||
}
|
||||
|
||||
i++;
|
||||
} while (W_ERROR_IS_OK(error));
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
@ -1,23 +1,10 @@
|
||||
# Registry backends
|
||||
|
||||
################################################
|
||||
# Start MODULE registry_nt4
|
||||
[MODULE::registry_nt4]
|
||||
INIT_FUNCTION = registry_nt4_init
|
||||
SUBSYSTEM = registry
|
||||
OBJ_FILES = \
|
||||
reg_backend_nt4.o
|
||||
PRIVATE_DEPENDENCIES = TDR_REGF
|
||||
# End MODULE registry_nt4
|
||||
################################################
|
||||
|
||||
[SUBSYSTEM::TDR_REGF]
|
||||
PUBLIC_DEPENDENCIES = TDR
|
||||
OBJ_FILES = tdr_regf.o
|
||||
|
||||
# Special support for external builddirs
|
||||
lib/registry/reg_backend_nt4.c: lib/registry/tdr_regf.c
|
||||
$(srcdir)/lib/registry/reg_backend_nt4.c: lib/registry/tdr_regf.c
|
||||
lib/registry/regf.c: lib/registry/tdr_regf.c
|
||||
$(srcdir)/lib/registry/regf.c: lib/registry/tdr_regf.c
|
||||
lib/registry/tdr_regf.h: lib/registry/tdr_regf.c
|
||||
lib/registry/tdr_regf.c: $(srcdir)/lib/registry/regf.idl
|
||||
@CPP="$(CPP)" srcdir="$(srcdir)" $(PERL) $(srcdir)/pidl/pidl $(PIDL_ARGS) \
|
||||
@ -27,51 +14,6 @@ lib/registry/tdr_regf.c: $(srcdir)/lib/registry/regf.idl
|
||||
clean::
|
||||
@-rm -f lib/registry/regf.h lib/registry/tdr_regf*
|
||||
|
||||
################################################
|
||||
# Start MODULE registry_w95
|
||||
[MODULE::registry_w95]
|
||||
INIT_FUNCTION = registry_w95_init
|
||||
SUBSYSTEM = registry
|
||||
OBJ_FILES = \
|
||||
reg_backend_w95.o
|
||||
# End MODULE registry_w95
|
||||
################################################
|
||||
|
||||
################################################
|
||||
# Start MODULE registry_dir
|
||||
[MODULE::registry_dir]
|
||||
INIT_FUNCTION = registry_dir_init
|
||||
SUBSYSTEM = registry
|
||||
OBJ_FILES = \
|
||||
reg_backend_dir.o
|
||||
PRIVATE_DEPENDENCIES = LIBTALLOC
|
||||
# End MODULE registry_dir
|
||||
################################################
|
||||
|
||||
################################################
|
||||
# Start MODULE registry_rpc
|
||||
[MODULE::registry_rpc]
|
||||
INIT_FUNCTION = registry_rpc_init
|
||||
OUTPUT_TYPE = INTEGRATED
|
||||
SUBSYSTEM = registry
|
||||
OBJ_FILES = \
|
||||
reg_backend_rpc.o
|
||||
PRIVATE_DEPENDENCIES = RPC_NDR_WINREG
|
||||
# End MODULE registry_rpc
|
||||
################################################
|
||||
|
||||
################################################
|
||||
# Start MODULE registry_ldb
|
||||
[MODULE::registry_ldb]
|
||||
INIT_FUNCTION = registry_ldb_init
|
||||
SUBSYSTEM = registry
|
||||
OBJ_FILES = \
|
||||
reg_backend_ldb.o
|
||||
PRIVATE_DEPENDENCIES = \
|
||||
LIBLDB
|
||||
# End MODULE registry_ldb
|
||||
################################################
|
||||
|
||||
################################################
|
||||
# Start SUBSYSTEM registry
|
||||
[LIBRARY::registry]
|
||||
@ -79,16 +21,30 @@ VERSION = 0.0.1
|
||||
SO_VERSION = 0
|
||||
DESCRIPTION = Windows-style registry library
|
||||
OBJ_FILES = \
|
||||
common/reg_interface.o \
|
||||
common/reg_util.o \
|
||||
reg_samba.o \
|
||||
patchfile.o
|
||||
PRIVATE_DEPENDENCIES = \
|
||||
LIBSAMBA-UTIL CHARSET
|
||||
interface.o \
|
||||
util.o \
|
||||
samba.o \
|
||||
patchfile_dotreg.o \
|
||||
patchfile_preg.o \
|
||||
patchfile.o \
|
||||
regf.o \
|
||||
hive.o \
|
||||
local.o \
|
||||
ldb.o \
|
||||
dir.o \
|
||||
rpc.o
|
||||
PUBLIC_DEPENDENCIES = \
|
||||
LIBSAMBA-UTIL CHARSET TDR_REGF LIBLDB \
|
||||
RPC_NDR_WINREG
|
||||
PUBLIC_HEADERS = registry.h
|
||||
# End MODULE registry_ldb
|
||||
################################################
|
||||
|
||||
[SUBSYSTEM::registry_common]
|
||||
PUBLIC_DEPENDENCIES = registry
|
||||
OBJ_FILES = tools/common.o
|
||||
PUBLIC_PROTO_HEADER = tools/common.h
|
||||
|
||||
################################################
|
||||
# Start BINARY regdiff
|
||||
[BINARY::regdiff]
|
||||
@ -106,7 +62,8 @@ MANPAGE = man/regdiff.1
|
||||
INSTALLDIR = BINDIR
|
||||
OBJ_FILES = tools/regpatch.o
|
||||
PRIVATE_DEPENDENCIES = \
|
||||
LIBSAMBA-CONFIG registry LIBPOPT POPT_SAMBA POPT_CREDENTIALS
|
||||
LIBSAMBA-CONFIG registry LIBPOPT POPT_SAMBA POPT_CREDENTIALS \
|
||||
registry_common
|
||||
MANPAGE = man/regpatch.1
|
||||
# End BINARY regpatch
|
||||
################################################
|
||||
@ -118,7 +75,7 @@ INSTALLDIR = BINDIR
|
||||
OBJ_FILES = tools/regshell.o
|
||||
PRIVATE_DEPENDENCIES = \
|
||||
LIBSAMBA-CONFIG LIBPOPT registry POPT_SAMBA POPT_CREDENTIALS \
|
||||
SMBREADLINE
|
||||
SMBREADLINE registry_common
|
||||
MANPAGE = man/regshell.1
|
||||
# End BINARY regshell
|
||||
################################################
|
||||
@ -129,7 +86,8 @@ MANPAGE = man/regshell.1
|
||||
INSTALLDIR = BINDIR
|
||||
OBJ_FILES = tools/regtree.o
|
||||
PRIVATE_DEPENDENCIES = \
|
||||
LIBSAMBA-CONFIG LIBPOPT registry POPT_SAMBA POPT_CREDENTIALS
|
||||
LIBSAMBA-CONFIG LIBPOPT registry POPT_SAMBA POPT_CREDENTIALS \
|
||||
registry_common
|
||||
MANPAGE = man/regtree.1
|
||||
# End BINARY regtree
|
||||
################################################
|
||||
|
333
source4/lib/registry/dir.c
Normal file
333
source4/lib/registry/dir.c
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Registry interface
|
||||
Copyright (C) Jelmer Vernooij 2004-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 "hive.h"
|
||||
#include "system/dir.h"
|
||||
#include "system/filesys.h"
|
||||
|
||||
struct dir_key {
|
||||
struct hive_key key;
|
||||
const char *path;
|
||||
};
|
||||
|
||||
static struct hive_operations reg_backend_dir;
|
||||
|
||||
static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *parent,
|
||||
const char *name, const char *classname,
|
||||
struct security_descriptor *desc,
|
||||
struct hive_key **result)
|
||||
{
|
||||
struct dir_key *dk = talloc_get_type(parent, struct dir_key);
|
||||
char *path;
|
||||
int ret;
|
||||
|
||||
path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);
|
||||
ret = mkdir(path, 0700);
|
||||
if (ret == 0) {
|
||||
struct dir_key *key = talloc(mem_ctx, struct dir_key);
|
||||
key->key.ops = ®_backend_dir;
|
||||
key->path = talloc_steal(key, path);
|
||||
*result = (struct hive_key *)key;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
if (errno == EEXIST)
|
||||
return WERR_ALREADY_EXISTS;
|
||||
printf("FAILED %s BECAUSE: %s\n", path, strerror(errno));
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
static WERROR reg_dir_del_key(const struct hive_key *k, const char *name)
|
||||
{
|
||||
struct dir_key *dk = talloc_get_type(k, struct dir_key);
|
||||
char *child = talloc_asprintf(NULL, "%s/%s", dk->path, name);
|
||||
WERROR ret;
|
||||
|
||||
if (rmdir(child) == 0)
|
||||
ret = WERR_OK;
|
||||
else if (errno == ENOENT)
|
||||
ret = WERR_NOT_FOUND;
|
||||
else
|
||||
ret = WERR_GENERAL_FAILURE;
|
||||
|
||||
talloc_free(child);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *parent,
|
||||
const char *name, struct hive_key **subkey)
|
||||
{
|
||||
DIR *d;
|
||||
char *fullpath;
|
||||
const struct dir_key *p = talloc_get_type(parent, struct dir_key);
|
||||
struct dir_key *ret;
|
||||
|
||||
if (name == NULL) {
|
||||
DEBUG(0, ("NULL pointer passed as directory name!"));
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
fullpath = talloc_asprintf(mem_ctx, "%s/%s", p->path, name);
|
||||
|
||||
d = opendir(fullpath);
|
||||
if (d == NULL) {
|
||||
DEBUG(3,("Unable to open '%s': %s\n", fullpath, strerror(errno)));
|
||||
return WERR_BADFILE;
|
||||
}
|
||||
closedir(d);
|
||||
ret = talloc(mem_ctx, struct dir_key);
|
||||
ret->key.ops = ®_backend_dir;
|
||||
ret->path = talloc_steal(ret, fullpath);
|
||||
*subkey = (struct hive_key *)ret;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *k, uint32_t idx,
|
||||
const char **name,
|
||||
const char **classname,
|
||||
NTTIME *last_mod_time)
|
||||
{
|
||||
struct dirent *e;
|
||||
const struct dir_key *dk = talloc_get_type(k, struct dir_key);
|
||||
int i = 0;
|
||||
DIR *d;
|
||||
|
||||
d = opendir(dk->path);
|
||||
|
||||
if (d == NULL)
|
||||
return WERR_INVALID_PARAM;
|
||||
|
||||
while((e = readdir(d))) {
|
||||
if(!ISDOT(e->d_name) && !ISDOTDOT(e->d_name)) {
|
||||
struct stat stbuf;
|
||||
char *thispath;
|
||||
|
||||
/* Check if file is a directory */
|
||||
asprintf(&thispath, "%s/%s", dk->path, e->d_name);
|
||||
stat(thispath, &stbuf);
|
||||
|
||||
if (!S_ISDIR(stbuf.st_mode)) {
|
||||
SAFE_FREE(thispath);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i == idx) {
|
||||
struct stat st;
|
||||
*name = talloc_strdup(mem_ctx, e->d_name);
|
||||
*classname = NULL;
|
||||
stat(thispath, &st);
|
||||
unix_to_nt_time(last_mod_time, st.st_mtime);
|
||||
SAFE_FREE(thispath);
|
||||
closedir(d);
|
||||
return WERR_OK;
|
||||
}
|
||||
i++;
|
||||
|
||||
SAFE_FREE(thispath);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
return WERR_NO_MORE_ITEMS;
|
||||
}
|
||||
|
||||
WERROR reg_open_directory(TALLOC_CTX *parent_ctx,
|
||||
const char *location, struct hive_key **key)
|
||||
{
|
||||
struct dir_key *dk;
|
||||
|
||||
if (location == NULL)
|
||||
return WERR_INVALID_PARAM;
|
||||
|
||||
dk = talloc(parent_ctx, struct dir_key);
|
||||
dk->key.ops = ®_backend_dir;
|
||||
dk->path = talloc_strdup(dk, location);
|
||||
*key = (struct hive_key *)dk;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
WERROR reg_create_directory(TALLOC_CTX *parent_ctx,
|
||||
const char *location, struct hive_key **key)
|
||||
{
|
||||
if (mkdir(location, 0700) != 0) {
|
||||
*key = NULL;
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
return reg_open_directory(parent_ctx, location, key);
|
||||
}
|
||||
|
||||
static WERROR reg_dir_get_info(TALLOC_CTX *ctx, const struct hive_key *key,
|
||||
const char **classname,
|
||||
uint32_t *num_subkeys,
|
||||
uint32_t *num_values,
|
||||
NTTIME *lastmod)
|
||||
{
|
||||
DIR *d;
|
||||
const struct dir_key *dk = talloc_get_type(key, struct dir_key);
|
||||
struct dirent *e;
|
||||
struct stat st;
|
||||
|
||||
SMB_ASSERT(key != NULL);
|
||||
|
||||
if (classname != NULL)
|
||||
*classname = NULL;
|
||||
|
||||
d = opendir(dk->path);
|
||||
if (d == NULL)
|
||||
return WERR_INVALID_PARAM;
|
||||
|
||||
if (num_subkeys != NULL)
|
||||
*num_subkeys = 0;
|
||||
|
||||
if (num_values != NULL)
|
||||
*num_values = 0;
|
||||
|
||||
while((e = readdir(d))) {
|
||||
if(!ISDOT(e->d_name) && !ISDOTDOT(e->d_name)) {
|
||||
char *path = talloc_asprintf(ctx, "%s/%s", dk->path, e->d_name);
|
||||
|
||||
if (stat(path, &st) < 0) {
|
||||
DEBUG(0, ("Error statting %s: %s\n", path, strerror(errno)));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISDIR(st.st_mode) && num_subkeys != NULL)
|
||||
(*num_subkeys)++;
|
||||
|
||||
if (!S_ISDIR(st.st_mode) && num_values != NULL)
|
||||
(*num_values)++;
|
||||
|
||||
talloc_free(path);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
if (lastmod != NULL)
|
||||
*lastmod = 0;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_dir_set_value (struct hive_key *key, const char *name,
|
||||
uint32_t type, const DATA_BLOB data)
|
||||
{
|
||||
const struct dir_key *dk = talloc_get_type(key, struct dir_key);
|
||||
char *path = talloc_asprintf(dk, "%s/%s", dk->path, name);
|
||||
|
||||
if (!file_save(path, data.data, data.length))
|
||||
return WERR_GENERAL_FAILURE;
|
||||
|
||||
/* FIXME: Type */
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_dir_get_value (TALLOC_CTX *mem_ctx,
|
||||
struct hive_key *key, const char *name,
|
||||
uint32_t *type, DATA_BLOB *data)
|
||||
{
|
||||
const struct dir_key *dk = talloc_get_type(key, struct dir_key);
|
||||
char *path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);
|
||||
size_t size;
|
||||
char *contents;
|
||||
|
||||
contents = file_load(path, &size, mem_ctx);
|
||||
talloc_free(path);
|
||||
if (contents == NULL)
|
||||
return WERR_NOT_FOUND;
|
||||
|
||||
if (type != NULL)
|
||||
*type = 4; /* FIXME */
|
||||
|
||||
data->data = (uint8_t *)contents;
|
||||
data->length = size;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_dir_enum_value (TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *key, int idx,
|
||||
const char **name,
|
||||
uint32_t *type, DATA_BLOB *data)
|
||||
{
|
||||
const struct dir_key *dk = talloc_get_type(key, struct dir_key);
|
||||
DIR *d;
|
||||
struct dirent *e;
|
||||
int i;
|
||||
|
||||
d = opendir(dk->path);
|
||||
if (d == NULL) {
|
||||
DEBUG(3,("Unable to open '%s': %s\n", dk->path, strerror(errno)));
|
||||
return WERR_BADFILE;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while((e = readdir(d))) {
|
||||
if (ISDOT(e->d_name) || ISDOTDOT(e->d_name))
|
||||
continue;
|
||||
|
||||
if (i == idx) {
|
||||
if (name != NULL)
|
||||
*name = talloc_strdup(mem_ctx, e->d_name);
|
||||
W_ERROR_NOT_OK_RETURN(reg_dir_get_value(mem_ctx, key, *name, type, data));
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
closedir(d);
|
||||
|
||||
return WERR_NO_MORE_ITEMS;
|
||||
}
|
||||
|
||||
|
||||
static WERROR reg_dir_del_value (struct hive_key *key, const char *name)
|
||||
{
|
||||
const struct dir_key *dk = talloc_get_type(key, struct dir_key);
|
||||
char *path = talloc_asprintf(key, "%s/%s", dk->path, name);
|
||||
if (unlink(path) < 0) {
|
||||
talloc_free(path);
|
||||
if (errno == ENOENT)
|
||||
return WERR_NOT_FOUND;
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
talloc_free(path);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct hive_operations reg_backend_dir = {
|
||||
.name = "dir",
|
||||
.get_key_by_name = reg_dir_open_key,
|
||||
.get_key_info = reg_dir_get_info,
|
||||
.add_key = reg_dir_add_key,
|
||||
.del_key = reg_dir_del_key,
|
||||
.enum_key = reg_dir_key_by_index,
|
||||
.set_value = reg_dir_set_value,
|
||||
.get_value_by_name = reg_dir_get_value,
|
||||
.enum_value = reg_dir_enum_value,
|
||||
.delete_value = reg_dir_del_value,
|
||||
};
|
145
source4/lib/registry/hive.c
Normal file
145
source4/lib/registry/hive.c
Normal file
@ -0,0 +1,145 @@
|
||||
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Registry hive interface
|
||||
Copyright (C) Jelmer Vernooij 2003-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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "hive.h"
|
||||
#include "system/filesys.h"
|
||||
|
||||
/** Open a registry file/host/etc */
|
||||
_PUBLIC_ WERROR reg_open_hive(TALLOC_CTX *parent_ctx, const char *location,
|
||||
struct auth_session_info *session_info,
|
||||
struct cli_credentials *credentials,
|
||||
struct hive_key **root)
|
||||
{
|
||||
int fd, num;
|
||||
char peek[20];
|
||||
|
||||
/* Check for directory */
|
||||
if (directory_exist(location)) {
|
||||
return reg_open_directory(parent_ctx, location, root);
|
||||
}
|
||||
|
||||
fd = open(location, O_RDWR);
|
||||
if (fd == -1) {
|
||||
return WERR_BADFILE;
|
||||
}
|
||||
|
||||
num = read(fd, peek, 20);
|
||||
if (num == -1) {
|
||||
return WERR_BADFILE;
|
||||
}
|
||||
|
||||
if (!strncmp(peek, "regf", 4)) {
|
||||
close(fd);
|
||||
return reg_open_regf_file(parent_ctx, location, root);
|
||||
} else if (!strncmp(peek, "TDB file", 8)) {
|
||||
close(fd);
|
||||
return reg_open_ldb_file(parent_ctx, location, session_info, credentials, root);
|
||||
}
|
||||
|
||||
return WERR_BADFILE;
|
||||
}
|
||||
|
||||
_PUBLIC_ WERROR hive_key_get_info(TALLOC_CTX *mem_ctx, const struct hive_key *key,
|
||||
const char **classname, uint32_t *num_subkeys,
|
||||
uint32_t *num_values,
|
||||
NTTIME *last_change_time)
|
||||
{
|
||||
return key->ops->get_key_info(mem_ctx, key, classname, num_subkeys,
|
||||
num_values, last_change_time);
|
||||
}
|
||||
|
||||
_PUBLIC_ WERROR hive_key_add_name(TALLOC_CTX *ctx, const struct hive_key *parent_key,
|
||||
const char *name, const char *classname, struct security_descriptor *desc,
|
||||
struct hive_key **key)
|
||||
{
|
||||
SMB_ASSERT(strchr(name, '\\') == NULL);
|
||||
|
||||
return parent_key->ops->add_key(ctx, parent_key, name, classname, desc, key);
|
||||
}
|
||||
|
||||
_PUBLIC_ WERROR hive_key_del(const struct hive_key *key, const char *name)
|
||||
{
|
||||
return key->ops->del_key(key, name);
|
||||
}
|
||||
|
||||
_PUBLIC_ WERROR hive_get_key_by_name(TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *key, const char *name,
|
||||
struct hive_key **subkey)
|
||||
{
|
||||
return key->ops->get_key_by_name(mem_ctx, key, name, subkey);
|
||||
}
|
||||
|
||||
WERROR hive_enum_key(TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *key, uint32_t idx,
|
||||
const char **name,
|
||||
const char **classname,
|
||||
NTTIME *last_mod_time)
|
||||
{
|
||||
return key->ops->enum_key(mem_ctx, key, idx, name, classname,
|
||||
last_mod_time);
|
||||
}
|
||||
|
||||
WERROR hive_set_value(struct hive_key *key, const char *name, uint32_t type,
|
||||
const DATA_BLOB data)
|
||||
{
|
||||
if (key->ops->set_value == NULL)
|
||||
return WERR_NOT_SUPPORTED;
|
||||
|
||||
return key->ops->set_value(key, name, type, data);
|
||||
}
|
||||
|
||||
WERROR hive_get_value (TALLOC_CTX *mem_ctx,
|
||||
struct hive_key *key, const char *name,
|
||||
uint32_t *type, DATA_BLOB *data)
|
||||
{
|
||||
if (key->ops->get_value_by_name == NULL)
|
||||
return WERR_NOT_SUPPORTED;
|
||||
|
||||
return key->ops->get_value_by_name(mem_ctx, key, name, type, data);
|
||||
}
|
||||
|
||||
WERROR hive_get_value_by_index (TALLOC_CTX *mem_ctx,
|
||||
struct hive_key *key, uint32_t idx, const char **name,
|
||||
uint32_t *type, DATA_BLOB *data)
|
||||
{
|
||||
if (key->ops->enum_value == NULL)
|
||||
return WERR_NOT_SUPPORTED;
|
||||
|
||||
return key->ops->enum_value(mem_ctx, key, idx, name, type, data);
|
||||
}
|
||||
|
||||
|
||||
WERROR hive_del_value (struct hive_key *key, const char *name)
|
||||
{
|
||||
if (key->ops->delete_value == NULL)
|
||||
return WERR_NOT_SUPPORTED;
|
||||
|
||||
return key->ops->delete_value(key, name);
|
||||
}
|
||||
|
||||
WERROR hive_key_flush(struct hive_key *key)
|
||||
{
|
||||
if (key->ops->flush_key == NULL)
|
||||
return WERR_OK;
|
||||
|
||||
return key->ops->flush_key(key);
|
||||
}
|
197
source4/lib/registry/hive.h
Normal file
197
source4/lib/registry/hive.h
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Registry hive interface
|
||||
Copyright (C) Jelmer Vernooij 2003-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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __REGISTRY_HIVE_H__
|
||||
#define __REGISTRY_HIVE_H__
|
||||
|
||||
#include "core.h"
|
||||
#include "talloc.h"
|
||||
#include "librpc/gen_ndr/security.h"
|
||||
|
||||
/**
|
||||
* This file contains the hive API. This API is generally used for
|
||||
* reading a specific file that contains just one hive.
|
||||
*
|
||||
* Good examples are .DAT (NTUSER.DAT) files.
|
||||
*
|
||||
* This API does not have any notification support (that
|
||||
* should be provided by the registry implementation), nor
|
||||
* does it understand what predefined keys are.
|
||||
*/
|
||||
|
||||
struct hive_key {
|
||||
const struct hive_operations *ops;
|
||||
};
|
||||
|
||||
struct hive_operations {
|
||||
const char *name;
|
||||
|
||||
/**
|
||||
* Open a specific subkey
|
||||
*/
|
||||
WERROR (*enum_key) (TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *key, uint32_t idx,
|
||||
const char **name,
|
||||
const char **classname,
|
||||
NTTIME *last_mod_time);
|
||||
|
||||
/**
|
||||
* Open a subkey by name
|
||||
*/
|
||||
WERROR (*get_key_by_name) (TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *key, const char *name,
|
||||
struct hive_key **subkey);
|
||||
|
||||
/**
|
||||
* Add a new key.
|
||||
*/
|
||||
WERROR (*add_key) (TALLOC_CTX *ctx,
|
||||
const struct hive_key *parent_key, const char *name,
|
||||
const char *classname, struct security_descriptor *desc,
|
||||
struct hive_key **key);
|
||||
/**
|
||||
* Remove an existing key.
|
||||
*/
|
||||
WERROR (*del_key) (const struct hive_key *key, const char *name);
|
||||
|
||||
/**
|
||||
* Force write of a key to disk.
|
||||
*/
|
||||
WERROR (*flush_key) (struct hive_key *key);
|
||||
|
||||
/**
|
||||
* Retrieve a registry value with a specific index.
|
||||
*/
|
||||
WERROR (*enum_value) (TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *key, int idx,
|
||||
const char **name, uint32_t *type,
|
||||
DATA_BLOB *data);
|
||||
|
||||
/**
|
||||
* Retrieve a registry value with the specified name
|
||||
*/
|
||||
WERROR (*get_value_by_name) (TALLOC_CTX *mem_ctx,
|
||||
struct hive_key *key, const char *name,
|
||||
uint32_t *type, DATA_BLOB *data);
|
||||
|
||||
/**
|
||||
* Set a value on the specified registry key.
|
||||
*/
|
||||
WERROR (*set_value) (struct hive_key *key, const char *name,
|
||||
uint32_t type, const DATA_BLOB data);
|
||||
|
||||
/**
|
||||
* Remove a value.
|
||||
*/
|
||||
WERROR (*delete_value) (struct hive_key *key, const char *name);
|
||||
|
||||
/* Security Descriptors */
|
||||
|
||||
/**
|
||||
* Change the security descriptor on a registry key.
|
||||
*
|
||||
* This should return WERR_NOT_SUPPORTED if the underlying
|
||||
* format does not have a mechanism for storing
|
||||
* security descriptors.
|
||||
*/
|
||||
WERROR (*set_sec_desc) (struct hive_key *key,
|
||||
const struct security_descriptor *desc);
|
||||
|
||||
/**
|
||||
* Retrieve the security descriptor on a registry key.
|
||||
*
|
||||
* This should return WERR_NOT_SUPPORTED if the underlying
|
||||
* format does not have a mechanism for storing
|
||||
* security descriptors.
|
||||
*/
|
||||
WERROR (*get_sec_desc) (TALLOC_CTX *ctx,
|
||||
const struct hive_key *key,
|
||||
struct security_descriptor **desc);
|
||||
|
||||
/**
|
||||
* Retrieve general information about a key.
|
||||
*/
|
||||
WERROR (*get_key_info) (TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *key,
|
||||
const char **classname,
|
||||
uint32_t *num_subkeys,
|
||||
uint32_t *num_values,
|
||||
NTTIME *last_change_time);
|
||||
};
|
||||
|
||||
struct cli_credentials;
|
||||
struct auth_session_info;
|
||||
|
||||
WERROR reg_open_hive(TALLOC_CTX *parent_ctx, const char *location,
|
||||
struct auth_session_info *session_info,
|
||||
struct cli_credentials *credentials,
|
||||
struct hive_key **root);
|
||||
WERROR hive_key_get_info(TALLOC_CTX *mem_ctx, const struct hive_key *key,
|
||||
const char **classname, uint32_t *num_subkeys,
|
||||
uint32_t *num_values,
|
||||
NTTIME *last_change_time);
|
||||
WERROR hive_key_add_name(TALLOC_CTX *ctx, const struct hive_key *parent_key,
|
||||
const char *name, const char *classname, struct security_descriptor *desc,
|
||||
struct hive_key **key);
|
||||
_PUBLIC_ WERROR hive_key_del(const struct hive_key *key, const char *name);
|
||||
_PUBLIC_ WERROR hive_get_key_by_name(TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *key, const char *name,
|
||||
struct hive_key **subkey);
|
||||
WERROR hive_enum_key(TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *key, uint32_t idx,
|
||||
const char **name,
|
||||
const char **classname,
|
||||
NTTIME *last_mod_time);
|
||||
|
||||
WERROR hive_set_value (struct hive_key *key, const char *name,
|
||||
uint32_t type, const DATA_BLOB data);
|
||||
|
||||
WERROR hive_get_value (TALLOC_CTX *mem_ctx,
|
||||
struct hive_key *key, const char *name,
|
||||
uint32_t *type, DATA_BLOB *data);
|
||||
WERROR hive_get_value_by_index (TALLOC_CTX *mem_ctx,
|
||||
struct hive_key *key, uint32_t idx, const char **name,
|
||||
uint32_t *type, DATA_BLOB *data);
|
||||
|
||||
WERROR hive_del_value (struct hive_key *key, const char *name);
|
||||
|
||||
WERROR hive_key_flush(struct hive_key *key);
|
||||
|
||||
|
||||
/* Individual backends */
|
||||
WERROR reg_open_directory(TALLOC_CTX *parent_ctx,
|
||||
const char *location, struct hive_key **key);
|
||||
WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx,
|
||||
const char *location, struct hive_key **key);
|
||||
WERROR reg_open_ldb_file(TALLOC_CTX *parent_ctx, const char *location,
|
||||
struct auth_session_info *session_info,
|
||||
struct cli_credentials *credentials,
|
||||
struct hive_key **k);
|
||||
|
||||
|
||||
WERROR reg_create_directory(TALLOC_CTX *parent_ctx,
|
||||
const char *location, struct hive_key **key);
|
||||
WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx,
|
||||
const char *location,
|
||||
int major_version,
|
||||
struct hive_key **key);
|
||||
|
||||
|
||||
#endif /* __REGISTRY_HIVE_H__ */
|
277
source4/lib/registry/interface.c
Normal file
277
source4/lib/registry/interface.c
Normal file
@ -0,0 +1,277 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Transparent registry backend handling
|
||||
Copyright (C) Jelmer Vernooij 2003-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 "lib/util/dlinklist.h"
|
||||
#include "lib/registry/registry.h"
|
||||
#include "system/filesys.h"
|
||||
#include "build.h"
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Main registry functions
|
||||
*/
|
||||
|
||||
const struct reg_predefined_key reg_predefined_keys[] = {
|
||||
{HKEY_CLASSES_ROOT,"HKEY_CLASSES_ROOT" },
|
||||
{HKEY_CURRENT_USER,"HKEY_CURRENT_USER" },
|
||||
{HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE" },
|
||||
{HKEY_PERFORMANCE_DATA, "HKEY_PERFORMANCE_DATA" },
|
||||
{HKEY_USERS, "HKEY_USERS" },
|
||||
{HKEY_CURRENT_CONFIG, "HKEY_CURRENT_CONFIG" },
|
||||
{HKEY_DYN_DATA, "HKEY_DYN_DATA" },
|
||||
{HKEY_PERFORMANCE_TEXT, "HKEY_PERFORMANCE_TEXT" },
|
||||
{HKEY_PERFORMANCE_NLSTEXT, "HKEY_PERFORMANCE_NLSTEXT" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/** Obtain name of specific hkey. */
|
||||
_PUBLIC_ const char *reg_get_predef_name(uint32_t hkey)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; reg_predefined_keys[i].name; i++) {
|
||||
if (reg_predefined_keys[i].handle == hkey)
|
||||
return reg_predefined_keys[i].name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Get predefined key by name. */
|
||||
_PUBLIC_ WERROR reg_get_predefined_key_by_name(struct registry_context *ctx,
|
||||
const char *name,
|
||||
struct registry_key **key)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; reg_predefined_keys[i].name; i++) {
|
||||
if (!strcasecmp(reg_predefined_keys[i].name, name))
|
||||
return reg_get_predefined_key(ctx, reg_predefined_keys[i].handle,
|
||||
key);
|
||||
}
|
||||
|
||||
DEBUG(1, ("No predefined key with name '%s'\n", name));
|
||||
|
||||
return WERR_BADFILE;
|
||||
}
|
||||
|
||||
/** Get predefined key by id. */
|
||||
_PUBLIC_ WERROR reg_get_predefined_key(const struct registry_context *ctx,
|
||||
uint32_t hkey, struct registry_key **key)
|
||||
{
|
||||
return ctx->ops->get_predefined_key(ctx, hkey, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a key
|
||||
* First tries to use the open_key function from the backend
|
||||
* then falls back to get_subkey_by_name and later get_subkey_by_index
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent,
|
||||
const char *name, struct registry_key **result)
|
||||
{
|
||||
if (parent == NULL) {
|
||||
DEBUG(0, ("Invalid parent key specified for open of '%s'\n", name));
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (parent->context->ops->open_key == NULL) {
|
||||
DEBUG(0, ("Registry backend doesn't have open_key!\n"));
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return parent->context->ops->open_key(mem_ctx, parent, name, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value by index
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key,
|
||||
uint32_t idx,
|
||||
const char **name,
|
||||
uint32_t *type,
|
||||
DATA_BLOB *data)
|
||||
{
|
||||
if (key == NULL)
|
||||
return WERR_INVALID_PARAM;
|
||||
|
||||
if (key->context->ops->enum_value == NULL)
|
||||
return WERR_NOT_SUPPORTED;
|
||||
|
||||
return key->context->ops->enum_value(mem_ctx, key, idx, name, type,
|
||||
data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of subkeys.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_get_info(TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key,
|
||||
const char **classname,
|
||||
uint32_t *num_subkeys,
|
||||
uint32_t *num_values,
|
||||
NTTIME *last_change_time)
|
||||
{
|
||||
if (key == NULL)
|
||||
return WERR_INVALID_PARAM;
|
||||
|
||||
if (key->context->ops->get_key_info == NULL)
|
||||
return WERR_NOT_SUPPORTED;
|
||||
|
||||
return key->context->ops->get_key_info(mem_ctx,
|
||||
key, classname, num_subkeys,
|
||||
num_values, last_change_time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subkey by index.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key, int idx, const char **name,
|
||||
const char **keyclass, NTTIME *last_changed_time)
|
||||
{
|
||||
if (key == NULL)
|
||||
return WERR_INVALID_PARAM;
|
||||
|
||||
if (key->context->ops->enum_key == NULL)
|
||||
return WERR_NOT_SUPPORTED;
|
||||
|
||||
return key->context->ops->enum_key(mem_ctx, key, idx, name,
|
||||
keyclass, last_changed_time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value by name.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key,
|
||||
const char *name,
|
||||
uint32_t *type,
|
||||
DATA_BLOB *data)
|
||||
{
|
||||
if (key == NULL)
|
||||
return WERR_INVALID_PARAM;
|
||||
|
||||
if (key->context->ops->get_value == NULL)
|
||||
return WERR_NOT_SUPPORTED;
|
||||
|
||||
return key->context->ops->get_value(mem_ctx, key, name, type, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a key.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_del(struct registry_key *parent, const char *name)
|
||||
{
|
||||
if (parent == NULL)
|
||||
return WERR_INVALID_PARAM;
|
||||
|
||||
if (parent->context->ops->delete_key == NULL)
|
||||
return WERR_NOT_SUPPORTED;
|
||||
|
||||
return parent->context->ops->delete_key(parent, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a key.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_add_name(TALLOC_CTX *mem_ctx,
|
||||
struct registry_key *parent,
|
||||
const char *name, const char *key_class,
|
||||
struct security_descriptor *desc,
|
||||
struct registry_key **newkey)
|
||||
{
|
||||
if (parent == NULL)
|
||||
return WERR_INVALID_PARAM;
|
||||
|
||||
if (parent->context->ops->create_key == NULL) {
|
||||
DEBUG(1, ("Backend '%s' doesn't support method add_key\n",
|
||||
parent->context->ops->name));
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return parent->context->ops->create_key(mem_ctx, parent, name,
|
||||
key_class, desc, newkey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_val_set(struct registry_key *key, const char *value,
|
||||
uint32_t type, const DATA_BLOB data)
|
||||
{
|
||||
if (key == NULL)
|
||||
return WERR_INVALID_PARAM;
|
||||
|
||||
/* A 'real' set function has preference */
|
||||
if (key->context->ops->set_value == NULL) {
|
||||
DEBUG(1, ("Backend '%s' doesn't support method set_value\n",
|
||||
key->context->ops->name));
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return key->context->ops->set_value(key, value, type, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the security descriptor on a key.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_get_sec_desc(TALLOC_CTX *ctx,
|
||||
const struct registry_key *key,
|
||||
struct security_descriptor **secdesc)
|
||||
{
|
||||
if (key == NULL)
|
||||
return WERR_INVALID_PARAM;
|
||||
|
||||
/* A 'real' set function has preference */
|
||||
if (key->context->ops->get_security == NULL)
|
||||
return WERR_NOT_SUPPORTED;
|
||||
|
||||
return key->context->ops->get_security(ctx, key, secdesc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a value.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_del_value(struct registry_key *key, const char *valname)
|
||||
{
|
||||
if (key == NULL)
|
||||
return WERR_INVALID_PARAM;
|
||||
|
||||
if (key->context->ops->delete_value == NULL)
|
||||
return WERR_NOT_SUPPORTED;
|
||||
|
||||
return key->context->ops->delete_value(key, valname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush a key to disk.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_key_flush(struct registry_key *key)
|
||||
{
|
||||
if (key == NULL)
|
||||
return WERR_INVALID_PARAM;
|
||||
|
||||
if (key->context->ops->flush_key == NULL)
|
||||
return WERR_NOT_SUPPORTED;
|
||||
|
||||
return key->context->ops->flush_key(key);
|
||||
}
|
501
source4/lib/registry/ldb.c
Normal file
501
source4/lib/registry/ldb.c
Normal file
@ -0,0 +1,501 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Registry interface
|
||||
Copyright (C) Jelmer Vernooij 2004-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 "registry.h"
|
||||
#include "lib/ldb/include/ldb.h"
|
||||
#include "lib/ldb/include/ldb_errors.h"
|
||||
#include "db_wrap.h"
|
||||
#include "librpc/gen_ndr/winreg.h"
|
||||
|
||||
static struct hive_operations reg_backend_ldb;
|
||||
|
||||
struct ldb_key_data
|
||||
{
|
||||
struct hive_key key;
|
||||
struct ldb_context *ldb;
|
||||
struct ldb_dn *dn;
|
||||
struct ldb_message **subkeys, **values;
|
||||
int subkey_count, value_count;
|
||||
};
|
||||
|
||||
static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char **name,
|
||||
uint32_t *type, DATA_BLOB *data)
|
||||
{
|
||||
const struct ldb_val *val;
|
||||
if (name != NULL)
|
||||
*name = talloc_strdup(mem_ctx, ldb_msg_find_attr_as_string(msg, "value", NULL));
|
||||
|
||||
if (type != NULL)
|
||||
*type = ldb_msg_find_attr_as_uint(msg, "type", 0);
|
||||
val = ldb_msg_find_ldb_val(msg, "data");
|
||||
|
||||
switch (*type)
|
||||
{
|
||||
case REG_SZ:
|
||||
case REG_EXPAND_SZ:
|
||||
data->length = convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16,
|
||||
val->data, val->length, (void **)&data->data);
|
||||
break;
|
||||
|
||||
case REG_DWORD: {
|
||||
uint32_t tmp = strtoul((char *)val->data, NULL, 0);
|
||||
*data = data_blob_talloc(mem_ctx, &tmp, 4);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
*data = data_blob_talloc(mem_ctx, val->data, val->length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx,
|
||||
TALLOC_CTX *mem_ctx, const char *name,
|
||||
uint32_t type, DATA_BLOB data)
|
||||
{
|
||||
struct ldb_val val;
|
||||
struct ldb_message *msg = talloc_zero(mem_ctx, struct ldb_message);
|
||||
char *type_s;
|
||||
|
||||
ldb_msg_add_string(msg, "value", talloc_strdup(mem_ctx, name));
|
||||
|
||||
switch (type) {
|
||||
case REG_SZ:
|
||||
case REG_EXPAND_SZ:
|
||||
val.length = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8,
|
||||
(void *)data.data, data.length, (void **)&val.data);
|
||||
ldb_msg_add_value(msg, "data", &val, NULL);
|
||||
break;
|
||||
|
||||
case REG_DWORD:
|
||||
ldb_msg_add_string(msg, "data", talloc_asprintf(mem_ctx, "0x%x", IVAL(data.data, 0)));
|
||||
break;
|
||||
default:
|
||||
ldb_msg_add_value(msg, "data", &data, NULL);
|
||||
}
|
||||
|
||||
|
||||
type_s = talloc_asprintf(mem_ctx, "%u", type);
|
||||
ldb_msg_add_string(msg, "type", type_s);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
static int reg_close_ldb_key(struct ldb_key_data *key)
|
||||
{
|
||||
if (key->subkeys != NULL) {
|
||||
talloc_free(key->subkeys);
|
||||
key->subkeys = NULL;
|
||||
}
|
||||
|
||||
if (key->values != NULL) {
|
||||
talloc_free(key->values);
|
||||
key->values = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ldb_dn *reg_path_to_ldb(TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *from,
|
||||
const char *path, const char *add)
|
||||
{
|
||||
TALLOC_CTX *local_ctx;
|
||||
struct ldb_dn *ret;
|
||||
char *mypath = talloc_strdup(mem_ctx, path);
|
||||
char *begin;
|
||||
struct ldb_key_data *kd = talloc_get_type(from, struct ldb_key_data);
|
||||
struct ldb_context *ldb = kd->ldb;
|
||||
|
||||
local_ctx = talloc_new(mem_ctx);
|
||||
|
||||
if (add) {
|
||||
ret = ldb_dn_new(mem_ctx, ldb, add);
|
||||
} else {
|
||||
ret = ldb_dn_new(mem_ctx, ldb, NULL);
|
||||
}
|
||||
if (!ldb_dn_validate(ret)) {
|
||||
talloc_free(ret);
|
||||
talloc_free(local_ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (mypath) {
|
||||
char *keyname;
|
||||
|
||||
begin = strrchr(mypath, '\\');
|
||||
|
||||
if (begin) keyname = begin + 1;
|
||||
else keyname = mypath;
|
||||
|
||||
if(strlen(keyname)) {
|
||||
ldb_dn_add_base_fmt(ret, "key=%s", keyname);
|
||||
}
|
||||
|
||||
if(begin) {
|
||||
*begin = '\0';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ldb_dn_add_base(ret, kd->dn);
|
||||
|
||||
talloc_free(local_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static WERROR cache_subkeys(struct ldb_key_data *kd)
|
||||
{
|
||||
struct ldb_context *c = kd->ldb;
|
||||
struct ldb_result *res;
|
||||
int ret;
|
||||
|
||||
ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(key=*)", NULL, &res);
|
||||
|
||||
if (ret != LDB_SUCCESS) {
|
||||
DEBUG(0, ("Error getting subkeys for '%s': %s\n", ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
kd->subkey_count = res->count;
|
||||
kd->subkeys = talloc_steal(kd, res->msgs);
|
||||
talloc_free(res);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR cache_values(struct ldb_key_data *kd)
|
||||
{
|
||||
struct ldb_context *c = kd->ldb;
|
||||
struct ldb_result *res;
|
||||
int ret;
|
||||
|
||||
ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(value=*)", NULL, &res);
|
||||
|
||||
if (ret != LDB_SUCCESS) {
|
||||
DEBUG(0, ("Error getting values for '%s': %s\n", ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
kd->value_count = res->count;
|
||||
kd->values = talloc_steal(kd, res->msgs);
|
||||
talloc_free(res);
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
|
||||
static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *k, uint32_t idx,
|
||||
const char **name,
|
||||
const char **classname,
|
||||
NTTIME *last_mod_time)
|
||||
{
|
||||
struct ldb_message_element *el;
|
||||
struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
|
||||
|
||||
/* Do a search if necessary */
|
||||
if (kd->subkeys == NULL) {
|
||||
W_ERROR_NOT_OK_RETURN(cache_subkeys(kd));
|
||||
}
|
||||
|
||||
if (idx >= kd->subkey_count)
|
||||
return WERR_NO_MORE_ITEMS;
|
||||
|
||||
el = ldb_msg_find_element(kd->subkeys[idx], "key");
|
||||
SMB_ASSERT(el != NULL);
|
||||
SMB_ASSERT(el->num_values != 0);
|
||||
|
||||
if (name != NULL)
|
||||
*name = talloc_strdup(mem_ctx, (char *)el->values[0].data);
|
||||
|
||||
if (classname != NULL)
|
||||
*classname = NULL; /* TODO: Store properly */
|
||||
|
||||
if (last_mod_time != NULL)
|
||||
*last_mod_time = 0; /* TODO: we need to add this to the
|
||||
ldb backend properly */
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, const struct hive_key *k, int idx,
|
||||
const char **name, uint32_t *data_type, DATA_BLOB *data)
|
||||
{
|
||||
struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
|
||||
|
||||
/* Do the search if necessary */
|
||||
if (kd->values == NULL) {
|
||||
W_ERROR_NOT_OK_RETURN(cache_values(kd));
|
||||
}
|
||||
|
||||
if(idx >= kd->value_count) return WERR_NO_MORE_ITEMS;
|
||||
|
||||
reg_ldb_unpack_value(mem_ctx, kd->values[idx],
|
||||
name, data_type, data);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_get_value(TALLOC_CTX *mem_ctx, struct hive_key *k,
|
||||
const char *name, uint32_t *data_type, DATA_BLOB *data)
|
||||
{
|
||||
struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data);
|
||||
struct ldb_context *c = kd->ldb;
|
||||
struct ldb_result *res;
|
||||
int ret;
|
||||
char *query = talloc_asprintf(mem_ctx, "(value=%s)", name);
|
||||
|
||||
ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, query, NULL, &res);
|
||||
|
||||
talloc_free(query);
|
||||
|
||||
if (ret != LDB_SUCCESS) {
|
||||
DEBUG(0, ("Error getting values for '%s': %s\n", ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
if (res->count == 0)
|
||||
return WERR_NOT_FOUND;
|
||||
|
||||
reg_ldb_unpack_value(mem_ctx, res->msgs[0], NULL, data_type, data);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, const struct hive_key *h,
|
||||
const char *name, struct hive_key **key)
|
||||
{
|
||||
struct ldb_result *res;
|
||||
struct ldb_dn *ldap_path;
|
||||
int ret;
|
||||
struct ldb_key_data *newkd;
|
||||
struct ldb_key_data *kd = talloc_get_type(h, struct ldb_key_data);
|
||||
struct ldb_context *c = kd->ldb;
|
||||
|
||||
ldap_path = reg_path_to_ldb(mem_ctx, h, name, NULL);
|
||||
|
||||
ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL, &res);
|
||||
|
||||
if (ret != LDB_SUCCESS) {
|
||||
DEBUG(0, ("Error opening key '%s': %s\n",
|
||||
ldb_dn_get_linearized(ldap_path), ldb_errstring(c)));
|
||||
return WERR_FOOBAR;
|
||||
} else if (res->count == 0) {
|
||||
DEBUG(0, ("Key '%s' not found\n", ldb_dn_get_linearized(ldap_path)));
|
||||
talloc_free(res);
|
||||
return WERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
newkd = talloc_zero(mem_ctx, struct ldb_key_data);
|
||||
newkd->key.ops = ®_backend_ldb;
|
||||
newkd->ldb = talloc_reference(newkd, kd->ldb);
|
||||
newkd->dn = ldb_dn_copy(mem_ctx, res->msgs[0]->dn);
|
||||
|
||||
*key = (struct hive_key *)newkd;
|
||||
|
||||
talloc_free(res);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
WERROR reg_open_ldb_file(TALLOC_CTX *parent_ctx, const char *location,
|
||||
struct auth_session_info *session_info,
|
||||
struct cli_credentials *credentials,
|
||||
struct hive_key **k)
|
||||
{
|
||||
struct ldb_key_data *kd;
|
||||
struct ldb_context *wrap;
|
||||
|
||||
if (location == NULL)
|
||||
return WERR_INVALID_PARAM;
|
||||
|
||||
wrap = ldb_wrap_connect(parent_ctx, location, session_info,
|
||||
credentials, 0, NULL);
|
||||
|
||||
if (wrap == NULL) {
|
||||
DEBUG(1, (__FILE__": unable to connect\n"));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
ldb_set_debug_stderr(wrap);
|
||||
|
||||
kd = talloc_zero(parent_ctx, struct ldb_key_data);
|
||||
kd->key.ops = ®_backend_ldb;
|
||||
kd->ldb = talloc_reference(kd, wrap);
|
||||
talloc_set_destructor (kd, reg_close_ldb_key);
|
||||
kd->dn = ldb_dn_new(kd, wrap, "hive=NONE");
|
||||
|
||||
*k = (struct hive_key *)kd;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, const struct hive_key *parent,
|
||||
const char *name, const char *classname,
|
||||
struct security_descriptor *sd,
|
||||
struct hive_key **newkey)
|
||||
{
|
||||
const struct ldb_key_data *parentkd = (const struct ldb_key_data *)parent;
|
||||
struct ldb_message *msg;
|
||||
struct ldb_key_data *newkd;
|
||||
int ret;
|
||||
|
||||
msg = ldb_msg_new(mem_ctx);
|
||||
|
||||
msg->dn = reg_path_to_ldb(msg, parent, name, NULL);
|
||||
|
||||
ldb_msg_add_string(msg, "key", talloc_strdup(mem_ctx, name));
|
||||
if (classname != NULL)
|
||||
ldb_msg_add_string(msg, "classname", talloc_strdup(mem_ctx, classname));
|
||||
|
||||
ret = ldb_add(parentkd->ldb, msg);
|
||||
if (ret < 0) {
|
||||
DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parentkd->ldb)));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
DEBUG(2, ("key added: %s\n", ldb_dn_get_linearized(msg->dn)));
|
||||
|
||||
newkd = talloc_zero(mem_ctx, struct ldb_key_data);
|
||||
newkd->ldb = talloc_reference(newkd, parentkd->ldb);
|
||||
newkd->key.ops = ®_backend_ldb;
|
||||
newkd->dn = talloc_steal(newkd, msg->dn);
|
||||
|
||||
*newkey = (struct hive_key *)newkd;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_del_key (const struct hive_key *key, const char *child)
|
||||
{
|
||||
int ret;
|
||||
struct ldb_key_data *parentkd = talloc_get_type(key, struct ldb_key_data);
|
||||
struct ldb_dn *childdn;
|
||||
|
||||
childdn = ldb_dn_copy(parentkd->ldb, parentkd->dn);
|
||||
ldb_dn_add_child_fmt(childdn, "key=%s", child);
|
||||
|
||||
ret = ldb_delete(parentkd->ldb, childdn);
|
||||
|
||||
talloc_free(childdn);
|
||||
|
||||
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
|
||||
return WERR_NOT_FOUND;
|
||||
} else if (ret < 0) {
|
||||
DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(parentkd->ldb)));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_del_value (struct hive_key *key, const char *child)
|
||||
{
|
||||
int ret;
|
||||
struct ldb_key_data *kd = talloc_get_type(key, struct ldb_key_data);
|
||||
struct ldb_dn *childdn;
|
||||
|
||||
childdn = ldb_dn_copy(kd->ldb, kd->dn);
|
||||
ldb_dn_add_child_fmt(childdn, "value=%s", child);
|
||||
|
||||
ret = ldb_delete(kd->ldb, childdn);
|
||||
|
||||
talloc_free(childdn);
|
||||
|
||||
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
|
||||
return WERR_NOT_FOUND;
|
||||
} else if (ret < 0) {
|
||||
DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(kd->ldb)));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_set_value(struct hive_key *parent,
|
||||
const char *name, uint32_t type,
|
||||
const DATA_BLOB data)
|
||||
{
|
||||
struct ldb_message *msg;
|
||||
struct ldb_key_data *kd = talloc_get_type(parent, struct ldb_key_data);
|
||||
int ret;
|
||||
TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value");
|
||||
|
||||
msg = reg_ldb_pack_value(kd->ldb, mem_ctx, name, type, data);
|
||||
|
||||
msg->dn = ldb_dn_copy(msg, kd->dn);
|
||||
ldb_dn_add_child_fmt(msg->dn, "value=%s", name);
|
||||
|
||||
ret = ldb_add(kd->ldb, msg);
|
||||
if (ret < 0) {
|
||||
ret = ldb_modify(kd->ldb, msg);
|
||||
if (ret < 0) {
|
||||
DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(kd->ldb)));
|
||||
talloc_free(mem_ctx);
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_get_key_info(TALLOC_CTX *mem_ctx,
|
||||
const struct hive_key *key,
|
||||
const char **classname,
|
||||
uint32_t *num_subkeys,
|
||||
uint32_t *num_values,
|
||||
NTTIME *last_change_time)
|
||||
{
|
||||
struct ldb_key_data *kd = talloc_get_type(key, struct ldb_key_data);
|
||||
|
||||
/* FIXME */
|
||||
if (classname != NULL)
|
||||
*classname = NULL;
|
||||
|
||||
if (num_subkeys != NULL) {
|
||||
W_ERROR_NOT_OK_RETURN(cache_subkeys(kd));
|
||||
*num_subkeys = kd->subkey_count;
|
||||
}
|
||||
|
||||
if (num_values != NULL) {
|
||||
W_ERROR_NOT_OK_RETURN(cache_values(kd));
|
||||
*num_values = kd->value_count;
|
||||
}
|
||||
|
||||
if (last_change_time != NULL)
|
||||
*last_change_time = 0;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct hive_operations reg_backend_ldb = {
|
||||
.name = "ldb",
|
||||
.add_key = ldb_add_key,
|
||||
.del_key = ldb_del_key,
|
||||
.get_key_by_name = ldb_open_key,
|
||||
.enum_value = ldb_get_value_by_id,
|
||||
.enum_key = ldb_get_subkey_by_id,
|
||||
.set_value = ldb_set_value,
|
||||
.get_value_by_name = ldb_get_value,
|
||||
.delete_value = ldb_del_value,
|
||||
.get_key_info = ldb_get_key_info,
|
||||
};
|
333
source4/lib/registry/local.c
Normal file
333
source4/lib/registry/local.c
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Transparent registry backend handling
|
||||
Copyright (C) Jelmer Vernooij 2003-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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "lib/util/dlinklist.h"
|
||||
#include "lib/registry/registry.h"
|
||||
#include "system/filesys.h"
|
||||
#include "build.h"
|
||||
|
||||
struct reg_key_path {
|
||||
uint32_t predefined_key;
|
||||
const char **elements;
|
||||
};
|
||||
|
||||
struct registry_local {
|
||||
struct registry_context registry;
|
||||
|
||||
struct mountpoint {
|
||||
struct reg_key_path path;
|
||||
struct hive_key *key;
|
||||
struct mountpoint *prev, *next;
|
||||
} *mountpoints;
|
||||
|
||||
struct auth_session_info *session_info;
|
||||
struct cli_credentials *credentials;
|
||||
};
|
||||
|
||||
struct local_key {
|
||||
struct registry_key global;
|
||||
struct reg_key_path path;
|
||||
struct hive_key *hive_key;
|
||||
};
|
||||
|
||||
|
||||
struct registry_key *reg_import_hive_key(struct registry_context *ctx,
|
||||
struct hive_key *hive,
|
||||
uint32_t predefined_key,
|
||||
const char **elements)
|
||||
{
|
||||
struct local_key *local_key;
|
||||
struct reg_key_path parent_path;
|
||||
|
||||
parent_path.predefined_key = predefined_key;
|
||||
parent_path.elements = elements;
|
||||
|
||||
local_key = talloc(ctx, struct local_key);
|
||||
local_key->hive_key = talloc_steal(local_key, hive);
|
||||
local_key->global.context = talloc_reference(local_key, ctx);
|
||||
local_key->path = parent_path;
|
||||
|
||||
return (struct registry_key *)local_key;
|
||||
}
|
||||
|
||||
|
||||
static WERROR local_open_key(TALLOC_CTX *mem_ctx,
|
||||
struct registry_key *parent,
|
||||
const char *path,
|
||||
struct registry_key **result)
|
||||
{
|
||||
char *orig = talloc_strdup(mem_ctx, path),
|
||||
*curbegin = orig,
|
||||
*curend = strchr(orig, '\\');
|
||||
struct local_key *local_parent = talloc_get_type(parent, struct local_key);
|
||||
struct hive_key *curkey = local_parent->hive_key;
|
||||
WERROR error;
|
||||
const char **elements = NULL;
|
||||
int el;
|
||||
|
||||
if (local_parent->path.elements != NULL) {
|
||||
elements = talloc_array(mem_ctx, const char *,
|
||||
str_list_length(local_parent->path.elements) + 1);
|
||||
for (el = 0; local_parent->path.elements[el] != NULL; el++) {
|
||||
elements[el] = talloc_reference(elements,
|
||||
local_parent->path.elements[el]);
|
||||
}
|
||||
elements[el] = NULL;
|
||||
} else {
|
||||
elements = NULL;
|
||||
el = 0;
|
||||
}
|
||||
|
||||
while (curbegin != NULL && *curbegin) {
|
||||
if (curend != NULL)
|
||||
*curend = '\0';
|
||||
elements = talloc_realloc(mem_ctx, elements, const char *, el+2);
|
||||
elements[el] = talloc_strdup(elements, curbegin);
|
||||
el++;
|
||||
elements[el] = NULL;
|
||||
error = hive_get_key_by_name(mem_ctx, curkey, curbegin, &curkey);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(2, ("Opening key %s failed: %s\n", curbegin, win_errstr(error)));
|
||||
talloc_free(orig);
|
||||
return error;
|
||||
}
|
||||
if (curend == NULL)
|
||||
break;
|
||||
curbegin = curend + 1;
|
||||
curend = strchr(curbegin, '\\');
|
||||
}
|
||||
talloc_free(orig);
|
||||
|
||||
*result = reg_import_hive_key(local_parent->global.context, curkey,
|
||||
local_parent->path.predefined_key,
|
||||
talloc_steal(curkey, elements));
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
WERROR local_get_predefined_key (const struct registry_context *ctx,
|
||||
uint32_t key_id, struct registry_key **key)
|
||||
{
|
||||
struct registry_local *rctx = talloc_get_type(ctx, struct registry_local);
|
||||
struct mountpoint *mp;
|
||||
|
||||
for (mp = rctx->mountpoints; mp != NULL; mp = mp->next) {
|
||||
if (mp->path.predefined_key == key_id &&
|
||||
mp->path.elements == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (mp == NULL)
|
||||
return WERR_NOT_FOUND;
|
||||
|
||||
*key = reg_import_hive_key(ctx, mp->key,
|
||||
mp->path.predefined_key,
|
||||
mp->path.elements
|
||||
);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
WERROR local_enum_key(TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key, uint32_t idx,
|
||||
const char **name,
|
||||
const char **keyclass,
|
||||
NTTIME *last_changed_time)
|
||||
{
|
||||
const struct local_key *local = (const struct local_key *)key;
|
||||
|
||||
return hive_enum_key(mem_ctx, local->hive_key, idx, name, keyclass,
|
||||
last_changed_time);
|
||||
}
|
||||
|
||||
static WERROR local_create_key (TALLOC_CTX *mem_ctx,
|
||||
struct registry_key *parent_key,
|
||||
const char *name,
|
||||
const char *key_class,
|
||||
struct security_descriptor *security,
|
||||
struct registry_key **key)
|
||||
{
|
||||
const struct local_key *local_parent;
|
||||
struct hive_key *hivekey;
|
||||
const char **elements;
|
||||
int i;
|
||||
char *last_part;
|
||||
|
||||
last_part = strrchr(name, '\\');
|
||||
if (last_part == NULL) {
|
||||
last_part = name;
|
||||
local_parent = (const struct local_key *)parent_key;
|
||||
} else {
|
||||
W_ERROR_NOT_OK_RETURN(reg_open_key(mem_ctx, parent_key,
|
||||
talloc_strndup(mem_ctx, name, last_part-name),
|
||||
&local_parent));
|
||||
last_part++;
|
||||
}
|
||||
|
||||
W_ERROR_NOT_OK_RETURN(hive_key_add_name(mem_ctx, local_parent->hive_key,
|
||||
last_part, key_class, security, &hivekey));
|
||||
|
||||
if (local_parent->path.elements != NULL) {
|
||||
elements = talloc_array(hivekey, const char *,
|
||||
str_list_length(local_parent->path.elements)+2);
|
||||
for (i = 0; local_parent->path.elements[i] != NULL; i++) {
|
||||
elements[i] = talloc_reference(elements,
|
||||
local_parent->path.elements[i]);
|
||||
}
|
||||
} else {
|
||||
elements = talloc_array(hivekey, const char *, 2);
|
||||
i = 0;
|
||||
}
|
||||
|
||||
elements[i] = talloc_strdup(elements, name);
|
||||
elements[i+1] = NULL;
|
||||
|
||||
*key = reg_import_hive_key(local_parent->global.context, hivekey,
|
||||
local_parent->path.predefined_key,
|
||||
elements);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR local_set_value (struct registry_key *key, const char *name,
|
||||
uint32_t type, const DATA_BLOB data)
|
||||
{
|
||||
struct local_key *local = (struct local_key *)key;
|
||||
|
||||
return hive_set_value(local->hive_key, name, type, data);
|
||||
}
|
||||
|
||||
static WERROR local_get_value (TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key,
|
||||
const char *name, uint32_t *type, DATA_BLOB *data)
|
||||
{
|
||||
const struct local_key *local = (const struct local_key *)key;
|
||||
|
||||
return hive_get_value(mem_ctx, local->hive_key, name, type, data);
|
||||
}
|
||||
|
||||
static WERROR local_enum_value (TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key, uint32_t idx,
|
||||
const char **name,
|
||||
uint32_t *type,
|
||||
DATA_BLOB *data)
|
||||
{
|
||||
const struct local_key *local = (const struct local_key *)key;
|
||||
|
||||
return hive_get_value_by_index(mem_ctx, local->hive_key, idx,
|
||||
name, type, data);
|
||||
}
|
||||
|
||||
static WERROR local_delete_key (struct registry_key *key, const char *name)
|
||||
{
|
||||
const struct local_key *local = (const struct local_key *)key;
|
||||
|
||||
return hive_key_del(local->hive_key, name);
|
||||
}
|
||||
|
||||
static WERROR local_delete_value (struct registry_key *key, const char *name)
|
||||
{
|
||||
const struct local_key *local = (const struct local_key *)key;
|
||||
|
||||
return hive_del_value(local->hive_key, name);
|
||||
}
|
||||
|
||||
static WERROR local_flush_key (struct registry_key *key)
|
||||
{
|
||||
const struct local_key *local = (const struct local_key *)key;
|
||||
|
||||
return hive_key_flush(local->hive_key);
|
||||
}
|
||||
|
||||
static WERROR local_get_key_info (TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key,
|
||||
const char **classname,
|
||||
uint32_t *num_subkeys,
|
||||
uint32_t *num_values,
|
||||
NTTIME *last_change_time)
|
||||
{
|
||||
const struct local_key *local = (const struct local_key *)key;
|
||||
|
||||
return hive_key_get_info(mem_ctx, local->hive_key,
|
||||
classname, num_subkeys, num_values,
|
||||
last_change_time);
|
||||
}
|
||||
|
||||
const static struct registry_operations local_ops = {
|
||||
.name = "local",
|
||||
.open_key = local_open_key,
|
||||
.get_predefined_key = local_get_predefined_key,
|
||||
.enum_key = local_enum_key,
|
||||
.create_key = local_create_key,
|
||||
.set_value = local_set_value,
|
||||
.get_value = local_get_value,
|
||||
.enum_value = local_enum_value,
|
||||
.delete_key = local_delete_key,
|
||||
.delete_value = local_delete_value,
|
||||
.flush_key = local_flush_key,
|
||||
.get_key_info = local_get_key_info,
|
||||
};
|
||||
|
||||
WERROR reg_open_local(TALLOC_CTX *mem_ctx, struct registry_context **ctx,
|
||||
struct auth_session_info *session_info,
|
||||
struct cli_credentials *credentials)
|
||||
{
|
||||
struct registry_local *ret = talloc_zero(mem_ctx, struct registry_local);
|
||||
|
||||
W_ERROR_HAVE_NO_MEMORY(ret);
|
||||
|
||||
ret->registry.ops = &local_ops;
|
||||
ret->session_info = session_info;
|
||||
ret->credentials = credentials;
|
||||
|
||||
*ctx = (struct registry_context *)ret;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
WERROR reg_mount_hive(struct registry_context *rctx,
|
||||
struct hive_key *hive_key,
|
||||
uint32_t key_id,
|
||||
const char **elements)
|
||||
{
|
||||
struct registry_local *reg_local = talloc_get_type(rctx, struct registry_local);
|
||||
struct mountpoint *mp = talloc(rctx, struct mountpoint);
|
||||
int i = 0;
|
||||
|
||||
mp->path.predefined_key = key_id;
|
||||
mp->prev = mp->next = NULL;
|
||||
mp->key = hive_key;
|
||||
if (elements != NULL) {
|
||||
mp->path.elements = talloc_array(mp, const char *,
|
||||
str_list_length(elements));
|
||||
for (i = 0; elements[i] != NULL; i++) {
|
||||
mp->path.elements[i] = talloc_reference(mp->path.elements,
|
||||
elements[i]);
|
||||
}
|
||||
mp->path.elements[i] = NULL;
|
||||
} else {
|
||||
mp->path.elements = NULL;
|
||||
}
|
||||
|
||||
DLIST_ADD(reg_local->mountpoints, mp);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
@ -54,7 +54,7 @@
|
||||
<varlistentry>
|
||||
<term>--backend BACKEND</term>
|
||||
<listitem><para>Name of backend to load. Possible values are:
|
||||
w95, nt4, gconf, dir and rpc. The default is <emphasis>dir</emphasis>.
|
||||
creg, regf, dir and rpc. The default is <emphasis>dir</emphasis>.
|
||||
</para>
|
||||
<para>
|
||||
This argument can be specified twice: once for the first
|
||||
|
@ -49,7 +49,7 @@
|
||||
<varlistentry>
|
||||
<term>--backend BACKEND</term>
|
||||
<listitem><para>Name of backend to load. Possible values are:
|
||||
w95, nt4, gconf, dir and rpc. The default is <emphasis>dir</emphasis>.
|
||||
creg, regf, dir and rpc. The default is <emphasis>dir</emphasis>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
@ -48,7 +48,7 @@
|
||||
<varlistentry>
|
||||
<term>--backend BACKEND</term>
|
||||
<listitem><para>Name of backend to load. Possible values are:
|
||||
w95, nt4, gconf, dir and rpc. The default is <emphasis>dir</emphasis>.
|
||||
creg, regf, dir and rpc. The default is <emphasis>dir</emphasis>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
@ -48,7 +48,7 @@
|
||||
<varlistentry>
|
||||
<term>--backend BACKEND</term>
|
||||
<listitem><para>Name of backend to load. Possible values are:
|
||||
w95, nt4, gconf, dir and rpc. The default is <emphasis>dir</emphasis>.
|
||||
creg, regf, dir and rpc. The default is <emphasis>dir</emphasis>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Reading .REG files
|
||||
Reading registry patch files
|
||||
|
||||
Copyright (C) Jelmer Vernooij 2004
|
||||
Copyright (C) Jelmer Vernooij 2004-2007
|
||||
Copyright (C) Wilco Baan Hofman 2006
|
||||
|
||||
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
|
||||
@ -19,153 +20,191 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "lib/registry/patchfile.h"
|
||||
#include "lib/registry/registry.h"
|
||||
#include "system/filesys.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Registry patch files
|
||||
*/
|
||||
|
||||
#define DEFAULT_IDENT_STRING "SAMBA4 REGISTRY"
|
||||
_PUBLIC_ WERROR reg_preg_diff_load(int fd, const struct reg_diff_callbacks *callbacks, void *callback_data);
|
||||
|
||||
static struct reg_diff_key *diff_find_add_key(struct reg_diff *diff, const char *path)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; diff->numkeys; i++) {
|
||||
if (!strcasecmp(diff->keys[i].name, path))
|
||||
return &diff->keys[i];
|
||||
}
|
||||
|
||||
diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2);
|
||||
diff->keys[diff->numkeys].name = talloc_strdup(diff->keys, path);
|
||||
diff->keys[diff->numkeys].changetype = REG_DIFF_CHANGE_KEY;
|
||||
diff->keys[diff->numkeys].numvalues = 0;
|
||||
diff->keys[diff->numkeys].values = NULL;
|
||||
|
||||
diff->numkeys++;
|
||||
return NULL;
|
||||
}
|
||||
_PUBLIC_ WERROR reg_dotreg_diff_load(int fd, const struct reg_diff_callbacks *callbacks, void *callback_data);
|
||||
|
||||
/*
|
||||
* Generate difference between two keys
|
||||
*/
|
||||
static WERROR reg_generate_diff_key(struct reg_diff *diff, struct registry_key *oldkey, struct registry_key *newkey)
|
||||
WERROR reg_generate_diff_key(struct registry_key *oldkey,
|
||||
struct registry_key *newkey,
|
||||
const char *path,
|
||||
const struct reg_diff_callbacks *callbacks,
|
||||
void *callback_data)
|
||||
{
|
||||
int i;
|
||||
struct registry_key *t1, *t2;
|
||||
struct registry_value *v1, *v2;
|
||||
WERROR error1, error2;
|
||||
char *tmppath;
|
||||
const char *keyname1;
|
||||
WERROR error, error1, error2;
|
||||
TALLOC_CTX *mem_ctx = talloc_init("writediff");
|
||||
uint32_t old_num_subkeys, old_num_values,
|
||||
new_num_subkeys, new_num_values;
|
||||
|
||||
if (oldkey != NULL) {
|
||||
error = reg_key_get_info(mem_ctx, oldkey, NULL, &old_num_subkeys, &old_num_values,
|
||||
NULL);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Error occured while getting key info: %s\n",
|
||||
win_errstr(error)));
|
||||
return error;
|
||||
}
|
||||
} else {
|
||||
old_num_subkeys = 0;
|
||||
old_num_values = 0;
|
||||
}
|
||||
|
||||
/* Subkeys that were deleted */
|
||||
for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(mem_ctx, oldkey, i, &t1)); i++) {
|
||||
error2 = reg_key_get_subkey_by_name(mem_ctx, newkey, t1->name, &t2);
|
||||
|
||||
if (W_ERROR_IS_OK(error2))
|
||||
for (i = 0; i < old_num_subkeys; i++) {
|
||||
error1 = reg_key_get_subkey_by_index(mem_ctx, oldkey, i, &keyname1,
|
||||
NULL, NULL);
|
||||
if (!W_ERROR_IS_OK(error1)) {
|
||||
DEBUG(0, ("Error occured while getting subkey by index: %s\n",
|
||||
win_errstr(error2)));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (newkey != NULL) {
|
||||
error2 = reg_open_key(mem_ctx, newkey, keyname1, &t2);
|
||||
|
||||
if (W_ERROR_IS_OK(error2))
|
||||
continue;
|
||||
} else {
|
||||
error2 = WERR_DEST_NOT_FOUND;
|
||||
t2 = NULL;
|
||||
}
|
||||
|
||||
if (!W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) {
|
||||
DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2)));
|
||||
DEBUG(0, ("Error occured while getting subkey by name: %s\n",
|
||||
win_errstr(error2)));
|
||||
talloc_free(mem_ctx);
|
||||
return error2;
|
||||
}
|
||||
|
||||
/* newkey didn't have such a subkey, add del diff */
|
||||
diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2);
|
||||
diff->keys[diff->numkeys].name = talloc_strdup(diff->keys, t1->path);
|
||||
diff->keys[diff->numkeys].changetype = REG_DIFF_DEL_KEY;
|
||||
diff->numkeys++;
|
||||
tmppath = talloc_asprintf(mem_ctx, "%s\\%s", path, keyname1);
|
||||
callbacks->del_key(callback_data, tmppath);
|
||||
talloc_free(tmppath);
|
||||
}
|
||||
|
||||
if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) {
|
||||
DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1)));
|
||||
talloc_free(mem_ctx);
|
||||
return error1;
|
||||
if (newkey != NULL) {
|
||||
error = reg_key_get_info(mem_ctx, newkey, NULL, &new_num_subkeys, &new_num_values,
|
||||
NULL);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Error occured while getting key info: %s\n",
|
||||
win_errstr(error)));
|
||||
return error;
|
||||
}
|
||||
} else {
|
||||
new_num_subkeys = 0;
|
||||
new_num_values = 0;
|
||||
}
|
||||
|
||||
/* Subkeys that were added */
|
||||
for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(mem_ctx, newkey, i, &t1)); i++) {
|
||||
error2 = reg_key_get_subkey_by_name(mem_ctx, oldkey, t1->name, &t2);
|
||||
for(i = 0; i < new_num_subkeys; i++) {
|
||||
error1 = reg_key_get_subkey_by_index(mem_ctx, newkey, i, &keyname1,
|
||||
NULL, NULL);
|
||||
if (!W_ERROR_IS_OK(error1)) {
|
||||
DEBUG(0, ("Error occured while getting subkey by index: %s\n",
|
||||
win_errstr(error1)));
|
||||
talloc_free(mem_ctx);
|
||||
return error1;
|
||||
}
|
||||
|
||||
if (oldkey != NULL) {
|
||||
error2 = reg_open_key(mem_ctx, oldkey, keyname1, &t1);
|
||||
|
||||
if (W_ERROR_IS_OK(error2))
|
||||
continue;
|
||||
} else {
|
||||
t1 = NULL;
|
||||
error2 = WERR_DEST_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (W_ERROR_IS_OK(error2))
|
||||
continue;
|
||||
|
||||
if (!W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) {
|
||||
DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2)));
|
||||
DEBUG(0, ("Error occured while getting subkey by name: %s\n",
|
||||
win_errstr(error2)));
|
||||
talloc_free(mem_ctx);
|
||||
return error2;
|
||||
}
|
||||
|
||||
/* oldkey didn't have such a subkey, add add diff */
|
||||
diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2);
|
||||
diff->keys[diff->numkeys].name = talloc_strdup(diff->keys, t1->path);
|
||||
diff->keys[diff->numkeys].changetype = REG_DIFF_CHANGE_KEY;
|
||||
diff->keys[diff->numkeys].numvalues = 0;
|
||||
diff->keys[diff->numkeys].values = NULL;
|
||||
diff->numkeys++;
|
||||
tmppath = talloc_asprintf(mem_ctx, "%s\\%s", path, keyname1);
|
||||
callbacks->add_key(callback_data, tmppath);
|
||||
|
||||
reg_generate_diff_key(diff, t1, t2);
|
||||
}
|
||||
W_ERROR_NOT_OK_RETURN(
|
||||
reg_open_key(mem_ctx, newkey, keyname1, &t2));
|
||||
|
||||
if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) {
|
||||
DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1)));
|
||||
talloc_free(mem_ctx);
|
||||
return error1;
|
||||
reg_generate_diff_key(t1, t2, tmppath, callbacks, callback_data);
|
||||
talloc_free(tmppath);
|
||||
}
|
||||
|
||||
/* Values that were changed */
|
||||
for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, newkey, i, &v1)); i++) {
|
||||
struct reg_diff_key *thiskey = NULL;
|
||||
error2 = reg_key_get_value_by_name(mem_ctx, oldkey, v1->name, &v2);
|
||||
for(i = 0; i < new_num_values; i++) {
|
||||
const char *name;
|
||||
uint32_t type1, type2;
|
||||
DATA_BLOB contents1, contents2;
|
||||
|
||||
error1 = reg_key_get_value_by_index(mem_ctx, newkey, i,
|
||||
&name, &type1, &contents1);
|
||||
if (!W_ERROR_IS_OK(error1)) {
|
||||
DEBUG(0, ("Unable to get key by index: %s\n",
|
||||
win_errstr(error1)));
|
||||
talloc_free(mem_ctx);
|
||||
return error1;
|
||||
}
|
||||
|
||||
if (oldkey != NULL) {
|
||||
error2 = reg_key_get_value_by_name(mem_ctx, oldkey, name,
|
||||
&type2, &contents2);
|
||||
} else
|
||||
error2 = WERR_DEST_NOT_FOUND;
|
||||
|
||||
if(!W_ERROR_IS_OK(error2) &&
|
||||
!W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) {
|
||||
DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2)));
|
||||
DEBUG(0, ("Error occured while getting value by name: %s\n",
|
||||
win_errstr(error2)));
|
||||
talloc_free(mem_ctx);
|
||||
return error2;
|
||||
}
|
||||
|
||||
if (W_ERROR_IS_OK(error2) && data_blob_cmp(&v1->data, &v2->data) == 0)
|
||||
if (W_ERROR_IS_OK(error2) && data_blob_cmp(&contents1, &contents2) == 0)
|
||||
continue;
|
||||
|
||||
thiskey = diff_find_add_key(diff, oldkey->path);
|
||||
thiskey->values = talloc_realloc(diff, thiskey->values, struct reg_diff_value, thiskey->numvalues+2);
|
||||
thiskey->values[thiskey->numvalues].name = talloc_strdup(thiskey->values, v1->name);
|
||||
thiskey->values[thiskey->numvalues].type = v2->data_type;
|
||||
thiskey->values[thiskey->numvalues].changetype = REG_DIFF_SET_VAL;
|
||||
thiskey->values[thiskey->numvalues].data = data_blob_dup_talloc(thiskey->values, &v2->data);
|
||||
thiskey->numvalues++;
|
||||
}
|
||||
|
||||
if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) {
|
||||
DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1)));
|
||||
talloc_free(mem_ctx);
|
||||
return error1;
|
||||
callbacks->set_value(callback_data, path, name, type1, contents1);
|
||||
}
|
||||
|
||||
/* Values that were deleted */
|
||||
for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, oldkey, i, &v1)); i++) {
|
||||
struct reg_diff_key *thiskey = NULL;
|
||||
error2 = reg_key_get_value_by_name(mem_ctx, newkey, v1->name, &v2);
|
||||
for (i = 0; i < old_num_values; i++) {
|
||||
const char *name;
|
||||
error1 = reg_key_get_value_by_index(mem_ctx, oldkey, i, &name,
|
||||
NULL, NULL);
|
||||
if (!W_ERROR_IS_OK(error1)) {
|
||||
DEBUG(0, ("Error ocurred getting value by index: %s\n",
|
||||
win_errstr(error1)));
|
||||
talloc_free(mem_ctx);
|
||||
return error1;
|
||||
}
|
||||
|
||||
error2 = reg_key_get_value_by_name(mem_ctx, newkey, name, NULL,
|
||||
NULL);
|
||||
|
||||
if (W_ERROR_IS_OK(error2))
|
||||
continue;
|
||||
|
||||
if (!W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) {
|
||||
DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2)));
|
||||
DEBUG(0, ("Error occured while getting value by name: %s\n",
|
||||
win_errstr(error2)));
|
||||
return error2;
|
||||
}
|
||||
|
||||
thiskey = diff_find_add_key(diff, oldkey->path);
|
||||
thiskey->values = talloc_realloc(diff, thiskey->values, struct reg_diff_value, thiskey->numvalues+2);
|
||||
thiskey->values[thiskey->numvalues].name = talloc_strdup(thiskey->values, v1->name);
|
||||
thiskey->values[thiskey->numvalues].changetype = REG_DIFF_DEL_VAL;
|
||||
thiskey->numvalues++;
|
||||
}
|
||||
|
||||
if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) {
|
||||
DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1)));
|
||||
talloc_free(mem_ctx);
|
||||
return error1;
|
||||
callbacks->del_value(callback_data, path, name);
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
@ -175,244 +214,206 @@ static WERROR reg_generate_diff_key(struct reg_diff *diff, struct registry_key *
|
||||
/**
|
||||
* Generate diff between two registry contexts
|
||||
*/
|
||||
_PUBLIC_ struct reg_diff *reg_generate_diff(TALLOC_CTX *mem_ctx, struct registry_context *ctx1, struct registry_context *ctx2)
|
||||
_PUBLIC_ WERROR reg_generate_diff(struct registry_context *ctx1,
|
||||
struct registry_context *ctx2,
|
||||
const struct reg_diff_callbacks *callbacks,
|
||||
void *callback_data)
|
||||
{
|
||||
struct reg_diff *diff = talloc_zero(mem_ctx, struct reg_diff);
|
||||
int i;
|
||||
WERROR error;
|
||||
|
||||
for(i = HKEY_CLASSES_ROOT; i <= HKEY_PERFORMANCE_NLSTEXT; i++) {
|
||||
struct registry_key *r1, *r2;
|
||||
for(i = HKEY_FIRST; i <= HKEY_LAST; i++) {
|
||||
struct registry_key *r1 = NULL, *r2 = NULL;
|
||||
error = reg_get_predefined_key(ctx1, i, &r1);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
if (!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NOT_FOUND)) {
|
||||
DEBUG(0, ("Unable to open hive %s for backend 1\n", reg_get_predef_name(i)));
|
||||
continue;
|
||||
}
|
||||
|
||||
error = reg_get_predefined_key(ctx2, i, &r2);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
if (!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NOT_FOUND)) {
|
||||
DEBUG(0, ("Unable to open hive %s for backend 2\n", reg_get_predef_name(i)));
|
||||
}
|
||||
|
||||
if (r1 == NULL && r2 == NULL)
|
||||
continue;
|
||||
}
|
||||
|
||||
reg_generate_diff_key(diff, r1, r2);
|
||||
error = reg_generate_diff_key(r1, r2, reg_get_predef_name(i), callbacks, callback_data);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Unable to determine diff: %s\n", win_errstr(error)));
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save registry diff
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_diff_save(const struct reg_diff *diff, const char *filename)
|
||||
{
|
||||
int xf, i, j;
|
||||
|
||||
if (filename) {
|
||||
xf = open(filename, O_CREAT, 0755);
|
||||
if (xf == -1) {
|
||||
DEBUG(0, ("Unable to open %s\n", filename));
|
||||
return WERR_BADFILE;
|
||||
}
|
||||
} else
|
||||
xf = STDIN_FILENO;
|
||||
|
||||
fdprintf(xf, "%s\n\n", diff->format?diff->format:DEFAULT_IDENT_STRING);
|
||||
|
||||
for (i = 0; i < diff->numkeys; i++) {
|
||||
if (diff->keys[i].changetype == REG_DIFF_DEL_KEY) {
|
||||
fdprintf(xf, "-%s\n\n", diff->keys[i].name);
|
||||
continue;
|
||||
}
|
||||
|
||||
fdprintf(xf, "[%s]\n", diff->keys[i].name);
|
||||
|
||||
for (j = 0; j < diff->keys[i].numvalues; j++) {
|
||||
fdprintf(xf, "\"%s\"=", diff->keys[i].values[j].name);
|
||||
switch (diff->keys[i].values[j].changetype) {
|
||||
case REG_DIFF_DEL_VAL:
|
||||
fdprintf(xf, "-\n");
|
||||
break;
|
||||
case REG_DIFF_SET_VAL:
|
||||
fdprintf(xf, "%s:%s\n",
|
||||
str_regtype(diff->keys[i].values[j].type),
|
||||
reg_val_data_string(NULL,
|
||||
diff->keys[i].values[j].type,
|
||||
&diff->keys[i].values[j].data));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fdprintf(xf, "\n");
|
||||
if (callbacks->done != NULL) {
|
||||
callbacks->done(callback_data);
|
||||
}
|
||||
|
||||
close(xf);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load diff file
|
||||
*/
|
||||
_PUBLIC_ struct reg_diff *reg_diff_load(TALLOC_CTX *ctx, const char *fn)
|
||||
_PUBLIC_ WERROR reg_diff_load(const char *filename, const struct reg_diff_callbacks *callbacks, void *callback_data)
|
||||
{
|
||||
struct reg_diff *diff;
|
||||
int fd;
|
||||
char *line, *p, *q;
|
||||
struct reg_diff_key *curkey = NULL;
|
||||
struct reg_diff_value *curval;
|
||||
|
||||
fd = open(fn, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
DEBUG(0, ("Error opening registry patch file `%s'\n", fn));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
diff = talloc_zero(ctx, struct reg_diff);
|
||||
if (diff == NULL) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
char hdr[4];
|
||||
|
||||
diff->format = afdgets(fd, diff, 0);
|
||||
if (!diff->format) {
|
||||
talloc_free(diff);
|
||||
close(fd);
|
||||
return NULL;
|
||||
fd = open(filename, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
DEBUG(0, ("Error opening registry patch file `%s'\n", filename));
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
while ((line = afdgets(fd, diff, 0))) {
|
||||
/* Ignore comments and empty lines */
|
||||
if (strlen(line) == 0 || line[0] == ';') {
|
||||
curkey = NULL;
|
||||
talloc_free(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Start of key */
|
||||
if (line[0] == '[') {
|
||||
p = strchr_m(line, ']');
|
||||
if (p[strlen(p)-2] != ']') {
|
||||
DEBUG(0, ("Malformed line\n"));
|
||||
return NULL;
|
||||
}
|
||||
diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2);
|
||||
diff->keys[diff->numkeys].name = talloc_strndup(diff->keys, line+1, strlen(line)-2);
|
||||
diff->keys[diff->numkeys].changetype = REG_DIFF_CHANGE_KEY;
|
||||
diff->keys[diff->numkeys].numvalues = 0;
|
||||
diff->keys[diff->numkeys].values = NULL;
|
||||
curkey = &diff->keys[diff->numkeys];
|
||||
diff->numkeys++;
|
||||
talloc_free(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Deleting key */
|
||||
if (line[0] == '-') {
|
||||
diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2);
|
||||
diff->keys[diff->numkeys].name = talloc_strdup(diff->keys, line+1);
|
||||
diff->keys[diff->numkeys].changetype = REG_DIFF_DEL_KEY;
|
||||
diff->numkeys++;
|
||||
talloc_free(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Deleting/Changing value */
|
||||
p = strchr_m(line, '=');
|
||||
if (p == NULL) {
|
||||
DEBUG(0, ("Malformed line\n"));
|
||||
talloc_free(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
*p = '\0'; p++;
|
||||
|
||||
if (curkey == NULL) {
|
||||
DEBUG(0, ("Value change without key\n"));
|
||||
talloc_free(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
curkey->values = talloc_realloc(diff->keys, curkey->values, struct reg_diff_value, curkey->numvalues+2);
|
||||
curval = &curkey->values[curkey->numvalues];
|
||||
curkey->numvalues++;
|
||||
curval->name = talloc_strdup(curkey->values, line);
|
||||
|
||||
/* Delete value */
|
||||
if (strcmp(p, "-")) {
|
||||
curval->changetype = REG_DIFF_DEL_VAL;
|
||||
talloc_free(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
q = strchr_m(p, ':');
|
||||
if (q) {
|
||||
*q = '\0';
|
||||
q++;
|
||||
}
|
||||
|
||||
curval->changetype = REG_DIFF_SET_VAL;
|
||||
reg_string_to_val(curkey->values, q?p:"REG_SZ", q?q:p, &curval->type, &curval->data);
|
||||
|
||||
talloc_free(line);
|
||||
if (read(fd, &hdr, 4) != 4) {
|
||||
DEBUG(0, ("Error reading registry patch file `%s'\n", filename));
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return diff;
|
||||
/* Reset position in file */
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
#if 0
|
||||
if (strncmp(hdr, "CREG", 4) == 0) {
|
||||
/* Must be a W9x CREG Config.pol file */
|
||||
return reg_creg_diff_load(diff, fd);
|
||||
} else if (strncmp(hdr, "regf", 4) == 0) {
|
||||
/* Must be a REGF NTConfig.pol file */
|
||||
return reg_regf_diff_load(diff, fd);
|
||||
} else
|
||||
#endif
|
||||
if (strncmp(hdr, "PReg", 4) == 0) {
|
||||
/* Must be a GPO Registry.pol file */
|
||||
return reg_preg_diff_load(fd, callbacks, callback_data);
|
||||
} else {
|
||||
/* Must be a normal .REG file */
|
||||
return reg_dotreg_diff_load(fd, callbacks, callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply diff to a registry context
|
||||
* The reg_diff_apply functions
|
||||
*/
|
||||
_PUBLIC_ BOOL reg_diff_apply (const struct reg_diff *diff, struct registry_context *ctx)
|
||||
static WERROR reg_diff_apply_add_key(void *_ctx, const char *key_name)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx = talloc_init("apply_cmd_file");
|
||||
struct registry_key *tmp = NULL;
|
||||
struct registry_context *ctx = _ctx;
|
||||
struct registry_key *tmp;
|
||||
WERROR error;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < diff->numkeys; i++) {
|
||||
if (diff->keys[i].changetype == REG_DIFF_DEL_KEY) {
|
||||
error = reg_key_del_abs(ctx, diff->keys[i].name);
|
||||
error = reg_key_add_abs(ctx, ctx, key_name, 0, NULL, &tmp);
|
||||
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Unable to delete key '%s'\n", diff->keys[i].name));
|
||||
return False;
|
||||
}
|
||||
if (!W_ERROR_EQUAL(error, WERR_ALREADY_EXISTS) && !W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Error adding new key '%s': %s\n", key_name, win_errstr(error)));
|
||||
return error;
|
||||
}
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
static WERROR reg_diff_apply_del_key(void *_ctx, const char *key_name)
|
||||
{
|
||||
struct registry_context *ctx = _ctx;
|
||||
WERROR error;
|
||||
|
||||
/* Add / change key */
|
||||
error = reg_open_key_abs(mem_ctx, ctx, diff->keys[i].name, &tmp);
|
||||
error = reg_key_del_abs(ctx, key_name);
|
||||
|
||||
/* If we found it, apply the other bits, else create such a key */
|
||||
if (W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) {
|
||||
if(!W_ERROR_IS_OK(reg_key_add_abs(mem_ctx, ctx, diff->keys[i].name, 0, NULL, &tmp))) {
|
||||
DEBUG(0, ("Error adding new key '%s'\n", diff->keys[i].name));
|
||||
return False;
|
||||
}
|
||||
}
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Unable to delete key '%s'\n", key_name));
|
||||
return error;
|
||||
}
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
for (j = 0; j < diff->keys[i].numvalues; j++) {
|
||||
if (diff->keys[i].values[j].changetype == REG_DIFF_DEL_VAL) {
|
||||
error = reg_del_value(tmp, diff->keys[i].values[j].name);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Error deleting value '%s'\n", diff->keys[i].values[j].name));
|
||||
return False;
|
||||
}
|
||||
|
||||
error = reg_val_set(tmp, diff->keys[i].values[j].name,
|
||||
diff->keys[i].values[j].type,
|
||||
diff->keys[i].values[j].data);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Error setting value '%s'\n", diff->keys[i].values[j].name));
|
||||
return False;
|
||||
}
|
||||
}
|
||||
}
|
||||
static WERROR reg_diff_apply_set_value(void *_ctx, const char *path, const char *value_name, uint32_t value_type, DATA_BLOB value)
|
||||
{
|
||||
struct registry_context *ctx = _ctx;
|
||||
struct registry_key *tmp;
|
||||
WERROR error;
|
||||
|
||||
/* Open key */
|
||||
error = reg_open_key_abs(ctx, ctx, path, &tmp);
|
||||
|
||||
if (W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) {
|
||||
DEBUG(0, ("Error opening key '%s'\n", path));
|
||||
return error;
|
||||
}
|
||||
|
||||
return True;
|
||||
/* Set value */
|
||||
error = reg_val_set(tmp, value_name,
|
||||
value_type, value);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Error setting value '%s'\n", value_name));
|
||||
return error;
|
||||
}
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_diff_apply_del_value (void *_ctx, const char *key_name, const char *value_name)
|
||||
{
|
||||
struct registry_context *ctx = _ctx;
|
||||
struct registry_key *tmp;
|
||||
WERROR error;
|
||||
|
||||
/* Open key */
|
||||
error = reg_open_key_abs(ctx, ctx, key_name, &tmp);
|
||||
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Error opening key '%s'\n", key_name));
|
||||
return error;
|
||||
}
|
||||
|
||||
error = reg_del_value(tmp, value_name);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Error deleting value '%s'\n", value_name));
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_diff_apply_del_all_values(void *_ctx, const char *key_name)
|
||||
{
|
||||
struct registry_context *ctx = _ctx;
|
||||
struct registry_key *key;
|
||||
WERROR error;
|
||||
int i;
|
||||
uint32_t num_values;
|
||||
|
||||
error = reg_open_key_abs(ctx, ctx, key_name, &key);
|
||||
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Error opening key '%s'\n", key_name));
|
||||
return error;
|
||||
}
|
||||
|
||||
W_ERROR_NOT_OK_RETURN(reg_key_get_info(ctx, key,
|
||||
NULL,
|
||||
NULL,
|
||||
&num_values,
|
||||
NULL));
|
||||
|
||||
for (i = 0; i < num_values; i++) {
|
||||
const char *name;
|
||||
W_ERROR_NOT_OK_RETURN(reg_key_get_value_by_index(ctx, key, i, &name,
|
||||
NULL, NULL));
|
||||
W_ERROR_NOT_OK_RETURN(reg_del_value(key, name));
|
||||
}
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply diff to a registry context
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_diff_apply (const char *filename, struct registry_context *ctx)
|
||||
{
|
||||
struct reg_diff_callbacks callbacks;
|
||||
|
||||
callbacks.add_key = reg_diff_apply_add_key;
|
||||
callbacks.del_key = reg_diff_apply_del_key;
|
||||
callbacks.set_value = reg_diff_apply_set_value;
|
||||
callbacks.del_value = reg_diff_apply_del_value;
|
||||
callbacks.del_all_values = reg_diff_apply_del_all_values;
|
||||
callbacks.done = NULL;
|
||||
|
||||
return reg_diff_load(filename, &callbacks, ctx);
|
||||
}
|
||||
|
52
source4/lib/registry/patchfile.h
Normal file
52
source4/lib/registry/patchfile.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Patchfile interface
|
||||
Copyright (C) Jelmer Vernooij 2006
|
||||
Copyright (C) Wilco Baan Hofman 2006
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _PATCHFILE_H
|
||||
#define _PATCHFILE_H
|
||||
|
||||
#include "lib/registry/registry.h"
|
||||
|
||||
struct reg_diff_callbacks {
|
||||
WERROR (*add_key) (void *callback_data, const char *key_name);
|
||||
WERROR (*set_value) (void *callback_data, const char *key_name,
|
||||
const char *value_name, uint32_t value_type, DATA_BLOB value);
|
||||
WERROR (*del_value) (void *callback_data, const char *key_name, const char *value_name);
|
||||
WERROR (*del_key) (void *callback_data, const char *key_name);
|
||||
WERROR (*del_all_values) (void *callback_data, const char *key_name);
|
||||
WERROR (*done) (void *callback_data);
|
||||
};
|
||||
|
||||
_PUBLIC_ WERROR reg_diff_apply (const char *filename,
|
||||
struct registry_context *ctx);
|
||||
|
||||
_PUBLIC_ WERROR reg_generate_diff(struct registry_context *ctx1,
|
||||
struct registry_context *ctx2,
|
||||
const struct reg_diff_callbacks *callbacks,
|
||||
void *callback_data);
|
||||
_PUBLIC_ WERROR reg_dotreg_diff_save(TALLOC_CTX *ctx, const char *filename,
|
||||
struct reg_diff_callbacks **callbacks, void **callback_data);
|
||||
_PUBLIC_ WERROR reg_generate_diff_key(struct registry_key *oldkey,
|
||||
struct registry_key *newkey,
|
||||
const char *path,
|
||||
const struct reg_diff_callbacks *callbacks,
|
||||
void *callback_data);
|
||||
|
||||
#endif /* _PATCHFILE_H */
|
247
source4/lib/registry/patchfile_dotreg.c
Normal file
247
source4/lib/registry/patchfile_dotreg.c
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Reading .REG files
|
||||
|
||||
Copyright (C) Jelmer Vernooij 2004-2007
|
||||
Copyright (C) Wilco Baan Hofman 2006
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* FIXME Newer .REG files, created by Windows XP and above use unicode UTF-16 */
|
||||
|
||||
#include "includes.h"
|
||||
#include "lib/registry/patchfile.h"
|
||||
#include "lib/registry/registry.h"
|
||||
#include "system/filesys.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Registry patch files
|
||||
*/
|
||||
|
||||
#define HEADER_STRING "REGEDIT4"
|
||||
|
||||
struct dotreg_data {
|
||||
int fd;
|
||||
};
|
||||
|
||||
static WERROR reg_dotreg_diff_add_key(void *_data, const char *key_name)
|
||||
{
|
||||
struct dotreg_data *data = _data;
|
||||
|
||||
fdprintf(data->fd, "\n[%s]\n", key_name);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_dotreg_diff_del_key(void *_data, const char *key_name)
|
||||
{
|
||||
struct dotreg_data *data = _data;
|
||||
|
||||
fdprintf(data->fd, "\n[-%s]\n", key_name);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_dotreg_diff_set_value(void *_data, const char *path,
|
||||
const char *value_name, uint32_t value_type, DATA_BLOB value)
|
||||
{
|
||||
struct dotreg_data *data = _data;
|
||||
|
||||
fdprintf(data->fd, "\"%s\"=%s:%s\n",
|
||||
value_name, str_regtype(value_type),
|
||||
reg_val_data_string(NULL, value_type, value));
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_dotreg_diff_del_value(void *_data, const char *path, const char *value_name)
|
||||
{
|
||||
struct dotreg_data *data = _data;
|
||||
|
||||
fdprintf(data->fd, "\"%s\"=-\n", value_name);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_dotreg_diff_done(void *_data)
|
||||
{
|
||||
struct dotreg_data *data = _data;
|
||||
|
||||
close(data->fd);
|
||||
talloc_free(data);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_dotreg_diff_del_all_values (void *callback_data, const char *key_name)
|
||||
{
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save registry diff
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_dotreg_diff_save(TALLOC_CTX *ctx, const char *filename,
|
||||
struct reg_diff_callbacks **callbacks, void **callback_data)
|
||||
{
|
||||
struct dotreg_data *data;
|
||||
|
||||
data = talloc_zero(ctx, struct dotreg_data);
|
||||
*callback_data = data;
|
||||
|
||||
if (filename) {
|
||||
data->fd = open(filename, O_CREAT, 0755);
|
||||
if (data->fd == -1) {
|
||||
DEBUG(0, ("Unable to open %s\n", filename));
|
||||
return WERR_BADFILE;
|
||||
}
|
||||
} else {
|
||||
data->fd = STDOUT_FILENO;
|
||||
}
|
||||
|
||||
fdprintf(data->fd, "%s\n", HEADER_STRING);
|
||||
|
||||
*callbacks = talloc(ctx, struct reg_diff_callbacks);
|
||||
|
||||
(*callbacks)->add_key = reg_dotreg_diff_add_key;
|
||||
(*callbacks)->del_key = reg_dotreg_diff_del_key;
|
||||
(*callbacks)->set_value = reg_dotreg_diff_set_value;
|
||||
(*callbacks)->del_value = reg_dotreg_diff_del_value;
|
||||
(*callbacks)->del_all_values = reg_dotreg_diff_del_all_values;
|
||||
(*callbacks)->done = reg_dotreg_diff_done;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load diff file
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_dotreg_diff_load(int fd, const struct reg_diff_callbacks *callbacks, void *callback_data)
|
||||
{
|
||||
char *line, *p, *q;
|
||||
char *curkey = NULL;
|
||||
TALLOC_CTX *mem_ctx = talloc_init("reg_dotreg_diff_load");
|
||||
WERROR error;
|
||||
uint32_t value_type;
|
||||
DATA_BLOB value;
|
||||
|
||||
line = afdgets(fd, mem_ctx, 0);
|
||||
if (!line) {
|
||||
DEBUG(0, ("Can't read from file.\n"));
|
||||
talloc_free(mem_ctx);
|
||||
close(fd);
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
while ((line = afdgets(fd, mem_ctx, 0))) {
|
||||
/* Ignore comments and empty lines */
|
||||
if (strlen(line) == 0 || line[0] == ';') {
|
||||
talloc_free(line);
|
||||
|
||||
if (curkey) {
|
||||
talloc_free(curkey);
|
||||
}
|
||||
curkey = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Start of key */
|
||||
if (line[0] == '[') {
|
||||
p = strchr_m(line, ']');
|
||||
if (p[strlen(p)-1] != ']') {
|
||||
DEBUG(0, ("Missing ']'\n"));
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
/* Deleting key */
|
||||
if (line[1] == '-') {
|
||||
curkey = talloc_strndup(line, line+2, strlen(line)-3);
|
||||
|
||||
error = callbacks->del_key(callback_data, curkey);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0,("Error deleting key %s\n", curkey));
|
||||
talloc_free(mem_ctx);
|
||||
return error;
|
||||
}
|
||||
|
||||
talloc_free(line);
|
||||
curkey = NULL;
|
||||
continue;
|
||||
}
|
||||
curkey = talloc_strndup(mem_ctx, line+1, strlen(line)-2);
|
||||
|
||||
error = callbacks->add_key(callback_data, curkey);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0,("Error adding key %s\n", curkey));
|
||||
talloc_free(mem_ctx);
|
||||
return error;
|
||||
}
|
||||
|
||||
talloc_free(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Deleting/Changing value */
|
||||
p = strchr_m(line, '=');
|
||||
if (p == NULL) {
|
||||
DEBUG(0, ("Malformed line\n"));
|
||||
talloc_free(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
*p = '\0'; p++;
|
||||
|
||||
if (curkey == NULL) {
|
||||
DEBUG(0, ("Value change without key\n"));
|
||||
talloc_free(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Delete value */
|
||||
if (strcmp(p, "-")) {
|
||||
error = callbacks->del_value(callback_data, curkey, line);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Error deleting value %s in key %s\n", line, curkey));
|
||||
talloc_free(mem_ctx);
|
||||
return error;
|
||||
}
|
||||
|
||||
talloc_free(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
q = strchr_m(p, ':');
|
||||
if (q) {
|
||||
*q = '\0';
|
||||
q++;
|
||||
}
|
||||
|
||||
reg_string_to_val(line, q?p:"REG_SZ", q?q:p, &value_type, &value);
|
||||
|
||||
error = callbacks->set_value(callback_data, curkey, line, value_type, value);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Error setting value for %s in %s\n", line, curkey));
|
||||
talloc_free(mem_ctx);
|
||||
return error;
|
||||
}
|
||||
|
||||
talloc_free(line);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
270
source4/lib/registry/patchfile_preg.c
Normal file
270
source4/lib/registry/patchfile_preg.c
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Reading Registry.pol PReg registry files
|
||||
|
||||
Copyright (C) Wilco Baan Hofman 2006
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "lib/registry/registry.h"
|
||||
#include "system/filesys.h"
|
||||
#include "pstring.h"
|
||||
|
||||
struct preg_data {
|
||||
int fd;
|
||||
};
|
||||
|
||||
static WERROR preg_read_utf16(int fd, char *c)
|
||||
{
|
||||
uint16_t v;
|
||||
|
||||
if (read(fd, &v, 2) < 2) {
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
push_codepoint(c, v);
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
/* FIXME These functions need to be implemented */
|
||||
static WERROR reg_preg_diff_add_key(void *_data, const char *key_name)
|
||||
{
|
||||
struct preg_data *data = _data;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_preg_diff_del_key(void *_data, const char *key_name)
|
||||
{
|
||||
struct preg_data *data = _data;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_preg_diff_set_value(void *_data, const char *key_name, const char *value_name, uint32_t value_type, DATA_BLOB value_data)
|
||||
{
|
||||
struct preg_data *data = _data;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_preg_diff_del_value(void *_data, const char *key_name, const char *value_name)
|
||||
{
|
||||
struct preg_data *data = _data;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_preg_diff_del_all_values(void *_data, const char *key_name)
|
||||
{
|
||||
struct preg_data *data = _data;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_preg_diff_done(void *_data)
|
||||
{
|
||||
struct preg_data *data = _data;
|
||||
|
||||
close(data->fd);
|
||||
talloc_free(data);
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save registry diff
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_preg_diff_save(TALLOC_CTX *ctx, const char *filename, struct reg_diff_callbacks **callbacks, void **callback_data)
|
||||
{
|
||||
struct preg_data *data;
|
||||
struct {
|
||||
char hdr[4];
|
||||
uint32_t version;
|
||||
} preg_header;
|
||||
|
||||
|
||||
data = talloc_zero(ctx, struct preg_data);
|
||||
*callback_data = data;
|
||||
|
||||
if (filename) {
|
||||
data->fd = open(filename, O_CREAT, 0755);
|
||||
if (data->fd == -1) {
|
||||
DEBUG(0, ("Unable to open %s\n", filename));
|
||||
return WERR_BADFILE;
|
||||
}
|
||||
} else {
|
||||
data->fd = STDOUT_FILENO;
|
||||
}
|
||||
snprintf(preg_header.hdr, 4, "PReg");
|
||||
SIVAL(&preg_header, 4, 1);
|
||||
write(data->fd, (uint8_t *)&preg_header,8);
|
||||
|
||||
*callbacks = talloc(ctx, struct reg_diff_callbacks);
|
||||
|
||||
(*callbacks)->add_key = reg_preg_diff_add_key;
|
||||
(*callbacks)->del_key = reg_preg_diff_del_key;
|
||||
(*callbacks)->set_value = reg_preg_diff_set_value;
|
||||
(*callbacks)->del_value = reg_preg_diff_del_value;
|
||||
(*callbacks)->del_all_values = reg_preg_diff_del_all_values;
|
||||
(*callbacks)->done = reg_preg_diff_done;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
/**
|
||||
* Load diff file
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_preg_diff_load(int fd, const struct reg_diff_callbacks *callbacks, void *callback_data)
|
||||
{
|
||||
struct {
|
||||
char hdr[4];
|
||||
uint32_t version;
|
||||
} preg_header;
|
||||
pstring buf;
|
||||
char *buf_ptr = buf;
|
||||
TALLOC_CTX *mem_ctx = talloc_init("reg_preg_diff_load");
|
||||
|
||||
|
||||
/* Read first 8 bytes (the header) */
|
||||
if (read(fd, &preg_header, 8) != 8) {
|
||||
DEBUG(0, ("Could not read PReg file: %s\n",
|
||||
strerror(errno)));
|
||||
close(fd);
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
if (strncmp(preg_header.hdr, "PReg", 4) != 0) {
|
||||
DEBUG(0, ("This file is not a valid preg registry file\n"));
|
||||
close(fd);
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
if (preg_header.version > 1) {
|
||||
DEBUG(0, ("Warning: file format version is higher than expected.\n"));
|
||||
}
|
||||
|
||||
/* Read the entries */
|
||||
while(1) {
|
||||
char *key, *value_name;
|
||||
uint32_t value_type, length;
|
||||
DATA_BLOB data;
|
||||
|
||||
if (!W_ERROR_IS_OK(preg_read_utf16(fd, buf_ptr))) {
|
||||
break;
|
||||
}
|
||||
if (*buf_ptr != '[') {
|
||||
DEBUG(0, ("Error in PReg file.\n"));
|
||||
close(fd);
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
/* Get the path */
|
||||
buf_ptr = buf;
|
||||
while (W_ERROR_IS_OK(preg_read_utf16(fd, buf_ptr)) && *buf_ptr != ';' && buf_ptr-buf < sizeof(buf)) {
|
||||
buf_ptr++;
|
||||
}
|
||||
key = talloc_asprintf(mem_ctx, "\\%s", buf);
|
||||
|
||||
/* Get the name */
|
||||
buf_ptr = buf;
|
||||
while (W_ERROR_IS_OK(preg_read_utf16(fd, buf_ptr)) && *buf_ptr != ';' && buf_ptr-buf < sizeof(buf)) {
|
||||
buf_ptr++;
|
||||
}
|
||||
value_name = talloc_strdup(mem_ctx, buf);
|
||||
|
||||
/* Get the type */
|
||||
if (read(fd, &value_type, 4) < 4) {
|
||||
DEBUG(0, ("Error while reading PReg\n"));
|
||||
close(fd);
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
/* Read past delimiter */
|
||||
buf_ptr = buf;
|
||||
if (!(W_ERROR_IS_OK(preg_read_utf16(fd, buf_ptr)) && *buf_ptr == ';') && buf_ptr-buf < sizeof(buf)) {
|
||||
DEBUG(0, ("Error in PReg file.\n"));
|
||||
close(fd);
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
/* Get data length */
|
||||
if (read(fd, &length, 4) < 4) {
|
||||
DEBUG(0, ("Error while reading PReg\n"));
|
||||
close(fd);
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
/* Read past delimiter */
|
||||
buf_ptr = buf;
|
||||
if (!(W_ERROR_IS_OK(preg_read_utf16(fd, buf_ptr)) && *buf_ptr == ';') && buf_ptr-buf < sizeof(buf)) {
|
||||
DEBUG(0, ("Error in PReg file.\n"));
|
||||
close(fd);
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
/* Get the data */
|
||||
buf_ptr = buf;
|
||||
if (length < sizeof(buf) && read(fd, buf_ptr, length) != length) {
|
||||
DEBUG(0, ("Error while reading PReg\n"));
|
||||
close(fd);
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
data.length = length;
|
||||
data.data = talloc_memdup(mem_ctx, buf, length);
|
||||
|
||||
/* Check if delimiter is in place (whine if it isn't) */
|
||||
buf_ptr = buf;
|
||||
if (!(W_ERROR_IS_OK(preg_read_utf16(fd, buf_ptr)) && *buf_ptr == ']') && buf_ptr-buf < sizeof(buf)) {
|
||||
DEBUG(0, ("Warning: Missing ']' in PReg file, expected ']', got '%c' 0x%x.\n",*buf_ptr, *buf_ptr));
|
||||
}
|
||||
|
||||
if (strcasecmp(value_name, "**DelVals") == 0) {
|
||||
callbacks->del_all_values(callback_data, key);
|
||||
} else if (strncasecmp(value_name, "**Del.",6) == 0) {
|
||||
char *p = value_name+6;
|
||||
|
||||
callbacks->del_value(callback_data, key, p);
|
||||
} else if (strcasecmp(value_name, "**DeleteValues") == 0) {
|
||||
char *p, *q;
|
||||
|
||||
p = (char *) data.data;
|
||||
|
||||
while ((q = strchr_m(p, ';'))) {
|
||||
*q = '\0';
|
||||
q++;
|
||||
|
||||
callbacks->del_value(callback_data, key, p);
|
||||
|
||||
p = q;
|
||||
}
|
||||
callbacks->del_value(callback_data, key, p);
|
||||
} else if (strcasecmp(value_name, "**DeleteKeys") == 0) {
|
||||
char *p, *q, *full_key;
|
||||
|
||||
p = (char *) data.data;
|
||||
|
||||
while ((q = strchr_m(p, ';'))) {
|
||||
*q = '\0';
|
||||
q++;
|
||||
|
||||
full_key = talloc_asprintf(mem_ctx, "%s\\%s", key, p);
|
||||
callbacks->del_key(callback_data, full_key);
|
||||
talloc_free(full_key);
|
||||
|
||||
p = q;
|
||||
}
|
||||
full_key = talloc_asprintf(mem_ctx, "%s\\%s", key, p);
|
||||
callbacks->del_key(callback_data, full_key);
|
||||
talloc_free(full_key);
|
||||
} else {
|
||||
callbacks->add_key(callback_data, key);
|
||||
callbacks->set_value(callback_data, key, value_name, value_type, data);
|
||||
}
|
||||
talloc_free(key);
|
||||
talloc_free(value_name);
|
||||
talloc_free(data.data);
|
||||
}
|
||||
close(fd);
|
||||
return WERR_OK;
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Registry interface
|
||||
Copyright (C) Jelmer Vernooij 2004.
|
||||
|
||||
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 "registry.h"
|
||||
#include "system/dir.h"
|
||||
#include "system/filesys.h"
|
||||
|
||||
static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **result)
|
||||
{
|
||||
char *path;
|
||||
int ret;
|
||||
asprintf(&path, "%s%s\\%s", parent->hive->location, parent->path, name);
|
||||
path = reg_path_win2unix(path);
|
||||
ret = mkdir(path, 0700);
|
||||
SAFE_FREE(path);
|
||||
if(ret == 0)return WERR_OK; /* FIXME */
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
static WERROR reg_dir_del_key(const struct registry_key *k, const char *name)
|
||||
{
|
||||
char *child = talloc_asprintf(NULL, "%s/%s", (char *)k->backend_data, name);
|
||||
WERROR ret;
|
||||
|
||||
if (rmdir(child) == 0) ret = WERR_OK; else ret = WERR_GENERAL_FAILURE;
|
||||
|
||||
talloc_free(child);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, const struct registry_key *p, const char *name, struct registry_key **subkey)
|
||||
{
|
||||
DIR *d;
|
||||
char *fullpath, *unixpath;
|
||||
struct registry_key *ret;
|
||||
|
||||
if(!name) {
|
||||
DEBUG(0, ("NULL pointer passed as directory name!"));
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
|
||||
fullpath = talloc_asprintf(mem_ctx, "%s/%s", (char *)p->backend_data, name);
|
||||
unixpath = reg_path_win2unix(fullpath);
|
||||
|
||||
d = opendir(unixpath);
|
||||
if(!d) {
|
||||
DEBUG(3,("Unable to open '%s': %s\n", unixpath, strerror(errno)));
|
||||
return WERR_BADFILE;
|
||||
}
|
||||
closedir(d);
|
||||
ret = talloc(mem_ctx, struct registry_key);
|
||||
ret->hive = p->hive;
|
||||
ret->path = fullpath;
|
||||
ret->backend_data = unixpath;
|
||||
*subkey = ret;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_key **key)
|
||||
{
|
||||
struct dirent *e;
|
||||
char *fullpath = k->backend_data;
|
||||
int i = 0;
|
||||
DIR *d;
|
||||
|
||||
d = opendir(fullpath);
|
||||
|
||||
if(!d) return WERR_INVALID_PARAM;
|
||||
|
||||
while((e = readdir(d))) {
|
||||
if(!ISDOT(e->d_name) && !ISDOTDOT(e->d_name)) {
|
||||
struct stat stbuf;
|
||||
char *thispath;
|
||||
|
||||
/* Check if file is a directory */
|
||||
asprintf(&thispath, "%s/%s", fullpath, e->d_name);
|
||||
stat(thispath, &stbuf);
|
||||
|
||||
if(S_ISDIR(stbuf.st_mode)) {
|
||||
if(i == idx) {
|
||||
(*key) = talloc(mem_ctx, struct registry_key);
|
||||
(*key)->name = talloc_strdup(*key, e->d_name);
|
||||
(*key)->path = NULL;
|
||||
(*key)->backend_data = talloc_strdup(*key, thispath);
|
||||
SAFE_FREE(thispath);
|
||||
closedir(d);
|
||||
return WERR_OK;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
SAFE_FREE(thispath);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
return WERR_NO_MORE_ITEMS;
|
||||
}
|
||||
|
||||
static WERROR reg_dir_open(struct registry_hive *h, struct registry_key **key)
|
||||
{
|
||||
if(!h->location) return WERR_INVALID_PARAM;
|
||||
|
||||
*key = talloc(h, struct registry_key);
|
||||
(*key)->backend_data = talloc_strdup(*key, h->location);
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct hive_operations reg_backend_dir = {
|
||||
.name = "dir",
|
||||
.open_hive = reg_dir_open,
|
||||
.open_key = reg_dir_open_key,
|
||||
.add_key = reg_dir_add_key,
|
||||
.del_key = reg_dir_del_key,
|
||||
.get_subkey_by_index = reg_dir_key_by_index
|
||||
};
|
||||
|
||||
NTSTATUS registry_dir_init(void)
|
||||
{
|
||||
return registry_register(®_backend_dir);
|
||||
}
|
@ -1,405 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Registry interface
|
||||
Copyright (C) Jelmer Vernooij 2004.
|
||||
|
||||
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 "registry.h"
|
||||
#include "lib/ldb/include/ldb.h"
|
||||
#include "lib/ldb/include/ldb_errors.h"
|
||||
#include "db_wrap.h"
|
||||
#include "librpc/gen_ndr/winreg.h"
|
||||
|
||||
struct ldb_key_data
|
||||
{
|
||||
struct ldb_dn *dn;
|
||||
struct ldb_message **subkeys, **values;
|
||||
int subkey_count, value_count;
|
||||
};
|
||||
|
||||
static int ldb_free_hive (struct registry_hive *hive)
|
||||
{
|
||||
talloc_free(hive->backend_data);
|
||||
hive->backend_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char **name, uint32_t *type, DATA_BLOB *data)
|
||||
{
|
||||
const struct ldb_val *val;
|
||||
*name = talloc_strdup(mem_ctx, ldb_msg_find_attr_as_string(msg, "value", NULL));
|
||||
*type = ldb_msg_find_attr_as_uint(msg, "type", 0);
|
||||
val = ldb_msg_find_ldb_val(msg, "data");
|
||||
|
||||
switch (*type)
|
||||
{
|
||||
case REG_SZ:
|
||||
case REG_EXPAND_SZ:
|
||||
data->length = convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16, val->data, val->length, (void **)&data->data);
|
||||
break;
|
||||
|
||||
case REG_DWORD: {
|
||||
uint32_t tmp = strtoul((char *)val->data, NULL, 0);
|
||||
*data = data_blob_talloc(mem_ctx, &tmp, 4);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
*data = data_blob_talloc(mem_ctx, val->data, val->length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, const char *name, uint32_t type, DATA_BLOB data)
|
||||
{
|
||||
struct ldb_val val;
|
||||
struct ldb_message *msg = talloc_zero(mem_ctx, struct ldb_message);
|
||||
char *type_s;
|
||||
|
||||
ldb_msg_add_string(msg, "value", talloc_strdup(mem_ctx, name));
|
||||
|
||||
switch (type) {
|
||||
case REG_SZ:
|
||||
case REG_EXPAND_SZ:
|
||||
val.length = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8, (void *)data.data, data.length, (void **)&val.data);
|
||||
ldb_msg_add_value(msg, "data", &val, NULL);
|
||||
break;
|
||||
|
||||
case REG_DWORD:
|
||||
ldb_msg_add_string(msg, "data", talloc_asprintf(mem_ctx, "0x%x", IVAL(data.data, 0)));
|
||||
break;
|
||||
default:
|
||||
ldb_msg_add_value(msg, "data", &data, NULL);
|
||||
}
|
||||
|
||||
|
||||
type_s = talloc_asprintf(mem_ctx, "%u", type);
|
||||
ldb_msg_add_string(msg, "type", type_s);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
static int reg_close_ldb_key(struct registry_key *key)
|
||||
{
|
||||
struct ldb_key_data *kd = talloc_get_type(key->backend_data, struct ldb_key_data);
|
||||
/* struct ldb_context *c = key->hive->backend_data; */
|
||||
|
||||
if (kd->subkeys) {
|
||||
talloc_free(kd->subkeys);
|
||||
kd->subkeys = NULL;
|
||||
}
|
||||
|
||||
if (kd->values) {
|
||||
talloc_free(kd->values);
|
||||
kd->values = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ldb_dn *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const struct registry_key *from, const char *path, const char *add)
|
||||
{
|
||||
TALLOC_CTX *local_ctx;
|
||||
struct ldb_dn *ret;
|
||||
char *mypath = talloc_strdup(mem_ctx, path);
|
||||
char *begin;
|
||||
struct ldb_key_data *kd = talloc_get_type(from->backend_data, struct ldb_key_data);
|
||||
struct ldb_context *ldb = talloc_get_type(from->hive->backend_data, struct ldb_context);
|
||||
|
||||
local_ctx = talloc_new(mem_ctx);
|
||||
|
||||
if (add) {
|
||||
ret = ldb_dn_new(mem_ctx, ldb, add);
|
||||
} else {
|
||||
ret = ldb_dn_new(mem_ctx, ldb, NULL);
|
||||
}
|
||||
if ( ! ldb_dn_validate(ret)) {
|
||||
talloc_free(ret);
|
||||
talloc_free(local_ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while(mypath) {
|
||||
char *keyname;
|
||||
|
||||
begin = strrchr(mypath, '\\');
|
||||
|
||||
if (begin) keyname = begin + 1;
|
||||
else keyname = mypath;
|
||||
|
||||
if(strlen(keyname)) {
|
||||
ldb_dn_add_base_fmt(ret, "key=%s", keyname);
|
||||
}
|
||||
|
||||
if(begin) {
|
||||
*begin = '\0';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ldb_dn_add_base(ret, kd->dn);
|
||||
|
||||
talloc_free(local_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_key **subkey)
|
||||
{
|
||||
struct ldb_context *c = talloc_get_type(k->hive->backend_data, struct ldb_context);
|
||||
struct ldb_message_element *el;
|
||||
struct ldb_key_data *kd = talloc_get_type(k->backend_data, struct ldb_key_data);
|
||||
struct ldb_key_data *newkd;
|
||||
|
||||
/* Do a search if necessary */
|
||||
if (kd->subkeys == NULL) {
|
||||
struct ldb_result *res;
|
||||
int ret;
|
||||
|
||||
ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(key=*)", NULL, &res);
|
||||
|
||||
if (ret != LDB_SUCCESS) {
|
||||
DEBUG(0, ("Error getting subkeys for '%s': %s\n", ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
kd->subkey_count = res->count;
|
||||
kd->subkeys = talloc_steal(kd, res->msgs);
|
||||
talloc_free(res);
|
||||
}
|
||||
|
||||
if (idx >= kd->subkey_count) return WERR_NO_MORE_ITEMS;
|
||||
|
||||
el = ldb_msg_find_element(kd->subkeys[idx], "key");
|
||||
|
||||
*subkey = talloc(mem_ctx, struct registry_key);
|
||||
talloc_set_destructor(*subkey, reg_close_ldb_key);
|
||||
(*subkey)->name = talloc_strdup(mem_ctx, (char *)el->values[0].data);
|
||||
(*subkey)->backend_data = newkd = talloc_zero(*subkey, struct ldb_key_data);
|
||||
(*subkey)->last_mod = 0; /* TODO: we need to add this to the
|
||||
ldb backend properly */
|
||||
newkd->dn = ldb_dn_copy(mem_ctx, kd->subkeys[idx]->dn);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_value **value)
|
||||
{
|
||||
struct ldb_context *c = talloc_get_type(k->hive->backend_data, struct ldb_context);
|
||||
struct ldb_key_data *kd = talloc_get_type(k->backend_data, struct ldb_key_data);
|
||||
|
||||
/* Do the search if necessary */
|
||||
if (kd->values == NULL) {
|
||||
struct ldb_result *res;
|
||||
int ret;
|
||||
|
||||
ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(value=*)", NULL, &res);
|
||||
|
||||
if (ret != LDB_SUCCESS) {
|
||||
DEBUG(0, ("Error getting values for '%s': %s\n", ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
kd->value_count = res->count;
|
||||
kd->values = talloc_steal(kd, res->msgs);
|
||||
talloc_free(res);
|
||||
}
|
||||
|
||||
if(idx >= kd->value_count) return WERR_NO_MORE_ITEMS;
|
||||
|
||||
*value = talloc(mem_ctx, struct registry_value);
|
||||
|
||||
reg_ldb_unpack_value(mem_ctx, kd->values[idx], &(*value)->name, &(*value)->data_type, &(*value)->data);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, const struct registry_key *h, const char *name, struct registry_key **key)
|
||||
{
|
||||
struct ldb_context *c = talloc_get_type(h->hive->backend_data, struct ldb_context);
|
||||
struct ldb_result *res;
|
||||
struct ldb_dn *ldap_path;
|
||||
int ret;
|
||||
struct ldb_key_data *newkd;
|
||||
|
||||
ldap_path = reg_path_to_ldb(mem_ctx, h, name, NULL);
|
||||
|
||||
ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL, &res);
|
||||
|
||||
if (ret != LDB_SUCCESS) {
|
||||
DEBUG(0, ("Error opening key '%s': %s\n", ldb_dn_get_linearized(ldap_path), ldb_errstring(c)));
|
||||
return WERR_FOOBAR;
|
||||
} else if (res->count == 0) {
|
||||
talloc_free(res);
|
||||
return WERR_BADFILE;
|
||||
}
|
||||
|
||||
*key = talloc(mem_ctx, struct registry_key);
|
||||
talloc_set_destructor(*key, reg_close_ldb_key);
|
||||
(*key)->name = talloc_strdup(mem_ctx, strrchr(name, '\\')?strchr(name, '\\'):name);
|
||||
(*key)->backend_data = newkd = talloc_zero(*key, struct ldb_key_data);
|
||||
newkd->dn = ldb_dn_copy(mem_ctx, res->msgs[0]->dn);
|
||||
|
||||
talloc_free(res);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k)
|
||||
{
|
||||
struct ldb_key_data *kd;
|
||||
struct ldb_context *wrap;
|
||||
|
||||
if (!hive->location) return WERR_INVALID_PARAM;
|
||||
|
||||
wrap = ldb_wrap_connect(hive, hive->location, hive->session_info, hive->credentials, 0, NULL);
|
||||
|
||||
if(!wrap) {
|
||||
DEBUG(1, ("ldb_open_hive: unable to connect\n"));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
ldb_set_debug_stderr(wrap);
|
||||
hive->backend_data = wrap;
|
||||
|
||||
*k = talloc_zero(hive, struct registry_key);
|
||||
talloc_set_destructor (*k, reg_close_ldb_key);
|
||||
talloc_set_destructor (hive, ldb_free_hive);
|
||||
(*k)->name = talloc_strdup(*k, "");
|
||||
(*k)->backend_data = kd = talloc_zero(*k, struct ldb_key_data);
|
||||
kd->dn = ldb_dn_new(*k, wrap, "hive=NONE");
|
||||
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sd, struct registry_key **newkey)
|
||||
{
|
||||
struct ldb_context *ctx = talloc_get_type(parent->hive->backend_data, struct ldb_context);
|
||||
struct ldb_message *msg;
|
||||
struct ldb_key_data *newkd;
|
||||
int ret;
|
||||
|
||||
msg = ldb_msg_new(mem_ctx);
|
||||
|
||||
msg->dn = reg_path_to_ldb(msg, parent, name, NULL);
|
||||
|
||||
ldb_msg_add_string(msg, "key", talloc_strdup(mem_ctx, name));
|
||||
|
||||
ret = ldb_add(ctx, msg);
|
||||
if (ret < 0) {
|
||||
DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(ctx)));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
*newkey = talloc_zero(mem_ctx, struct registry_key);
|
||||
(*newkey)->name = talloc_strdup(mem_ctx, name);
|
||||
|
||||
(*newkey)->backend_data = newkd = talloc_zero(*newkey, struct ldb_key_data);
|
||||
newkd->dn = talloc_steal(newkd, msg->dn);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_del_key (const struct registry_key *key, const char *child)
|
||||
{
|
||||
struct ldb_context *ctx = talloc_get_type(key->hive->backend_data, struct ldb_context);
|
||||
int ret;
|
||||
struct ldb_key_data *kd = talloc_get_type(key->backend_data, struct ldb_key_data);
|
||||
struct ldb_dn *childdn;
|
||||
|
||||
childdn = ldb_dn_copy(ctx, kd->dn);
|
||||
ldb_dn_add_child_fmt(childdn, "key=%s", child);
|
||||
|
||||
ret = ldb_delete(ctx, childdn);
|
||||
|
||||
talloc_free(childdn);
|
||||
|
||||
if (ret < 0) {
|
||||
DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(ctx)));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_del_value (const struct registry_key *key, const char *child)
|
||||
{
|
||||
int ret;
|
||||
struct ldb_context *ctx = talloc_get_type(key->hive->backend_data, struct ldb_context);
|
||||
struct ldb_key_data *kd = talloc_get_type(key->backend_data, struct ldb_key_data);
|
||||
struct ldb_dn *childdn;
|
||||
|
||||
childdn = ldb_dn_copy(ctx, kd->dn);
|
||||
ldb_dn_add_child_fmt(childdn, "value=%s", child);
|
||||
|
||||
ret = ldb_delete(ctx, childdn);
|
||||
|
||||
talloc_free(childdn);
|
||||
|
||||
if (ret < 0) {
|
||||
DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(ctx)));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR ldb_set_value (const struct registry_key *parent, const char *name, uint32_t type, DATA_BLOB data)
|
||||
{
|
||||
struct ldb_context *ctx = talloc_get_type(parent->hive->backend_data, struct ldb_context);
|
||||
struct ldb_message *msg;
|
||||
struct ldb_key_data *kd = talloc_get_type(parent->backend_data, struct ldb_key_data);
|
||||
int ret;
|
||||
TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value");
|
||||
|
||||
msg = reg_ldb_pack_value(ctx, mem_ctx, name, type, data);
|
||||
|
||||
msg->dn = ldb_dn_copy(msg, kd->dn);
|
||||
ldb_dn_add_child_fmt(msg->dn, "value=%s", name);
|
||||
|
||||
ret = ldb_add(ctx, msg);
|
||||
if (ret < 0) {
|
||||
ret = ldb_modify(ctx, msg);
|
||||
if (ret < 0) {
|
||||
DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(ctx)));
|
||||
talloc_free(mem_ctx);
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct hive_operations reg_backend_ldb = {
|
||||
.name = "ldb",
|
||||
.add_key = ldb_add_key,
|
||||
.del_key = ldb_del_key,
|
||||
.open_hive = ldb_open_hive,
|
||||
.open_key = ldb_open_key,
|
||||
.get_value_by_index = ldb_get_value_by_id,
|
||||
.get_subkey_by_index = ldb_get_subkey_by_id,
|
||||
.set_value = ldb_set_value,
|
||||
.del_value = ldb_del_value,
|
||||
};
|
||||
|
||||
NTSTATUS registry_ldb_init(void)
|
||||
{
|
||||
return registry_register(®_backend_ldb);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,356 +0,0 @@
|
||||
/*
|
||||
Samba Unix/Linux SMB client utility libeditreg.c
|
||||
Copyright (C) 2004 Jelmer Vernooij, jelmer@samba.org
|
||||
|
||||
Backend for Windows '95 registry files. Explanation of file format
|
||||
comes from http://www.cs.mun.ca/~michael/regutils/.
|
||||
|
||||
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 "registry.h"
|
||||
#include "system/filesys.h"
|
||||
#include "system/shmem.h"
|
||||
|
||||
/**
|
||||
* The registry starts with a header that contains pointers to
|
||||
* the rgdb.
|
||||
*
|
||||
* After the main header follows the RGKN header (key index table).
|
||||
* The RGKN keys are listed after each other. They are put into
|
||||
* blocks, the first having a length of 0x2000 bytes, the others
|
||||
* being 0x1000 bytes long.
|
||||
*
|
||||
* After the RGKN header follow one or more RGDB blocks. These blocks
|
||||
* contain keys. A key is followed by its name and its values.
|
||||
*
|
||||
* Values are followed by their name and then their data.
|
||||
*
|
||||
* Basically the idea is that the RGKN contains the associations between
|
||||
* the keys and the RGDB contains the actual data.
|
||||
*/
|
||||
|
||||
typedef uint32_t DWORD;
|
||||
typedef unsigned short WORD;
|
||||
|
||||
typedef struct creg_block {
|
||||
DWORD CREG_ID; /* CREG */
|
||||
DWORD uk1;
|
||||
DWORD rgdb_offset;
|
||||
DWORD chksum;
|
||||
WORD num_rgdb;
|
||||
WORD flags;
|
||||
DWORD uk2;
|
||||
DWORD uk3;
|
||||
DWORD uk4;
|
||||
} CREG_HDR;
|
||||
|
||||
typedef struct rgkn_block {
|
||||
DWORD RGKN_ID; /* RGKN */
|
||||
DWORD size;
|
||||
DWORD root_offset;
|
||||
DWORD free_offset;
|
||||
DWORD flags;
|
||||
DWORD chksum;
|
||||
DWORD uk1;
|
||||
DWORD uk2;
|
||||
} RGKN_HDR;
|
||||
|
||||
typedef struct reg_id {
|
||||
WORD id;
|
||||
WORD rgdb;
|
||||
} REG_ID;
|
||||
|
||||
typedef struct rgkn_key {
|
||||
DWORD type; /* 0x00000000 = normal key, 0x80000000 = free block */
|
||||
DWORD hash; /* Contains either hash or size of free blocks that follows */
|
||||
DWORD next_free;
|
||||
DWORD parent_offset;
|
||||
DWORD first_child_offset;
|
||||
DWORD next_offset;
|
||||
REG_ID id;
|
||||
} RGKN_KEY;
|
||||
|
||||
|
||||
typedef struct rgdb_block {
|
||||
DWORD RGDB_ID; /* RGDB */
|
||||
DWORD size;
|
||||
DWORD unused_size;
|
||||
WORD flags;
|
||||
WORD section;
|
||||
DWORD free_offset; /* -1 if there is no free space */
|
||||
WORD max_id;
|
||||
WORD first_free_id;
|
||||
DWORD uk1;
|
||||
DWORD chksum;
|
||||
} RGDB_HDR;
|
||||
|
||||
typedef struct rgdb_key {
|
||||
DWORD size;
|
||||
REG_ID id;
|
||||
DWORD used_size;
|
||||
WORD name_len;
|
||||
WORD num_values;
|
||||
DWORD uk1;
|
||||
} RGDB_KEY;
|
||||
|
||||
typedef struct rgdb_value {
|
||||
DWORD type;
|
||||
DWORD uk1;
|
||||
WORD name_len;
|
||||
WORD data_len;
|
||||
} RGDB_VALUE;
|
||||
|
||||
typedef struct creg_struct_s {
|
||||
int fd;
|
||||
BOOL modified;
|
||||
char *base;
|
||||
struct stat sbuf;
|
||||
CREG_HDR *creg_hdr;
|
||||
RGKN_HDR *rgkn_hdr;
|
||||
RGDB_KEY ***rgdb_keys;
|
||||
} CREG;
|
||||
|
||||
#if 0 /* unused */
|
||||
#define RGKN_START_SIZE 0x2000
|
||||
#define RGKN_INC_SIZE 0x1000
|
||||
#endif
|
||||
|
||||
#define LOCN_RGKN(creg, o) ((RGKN_KEY *)((creg)->base + sizeof(CREG_HDR) + o))
|
||||
#define LOCN_RGDB_BLOCK(creg, o) (((creg)->base + (creg)->creg_hdr->rgdb_offset + o))
|
||||
#define LOCN_RGDB_KEY(creg, rgdb, id) ((RGDB_KEY *)((creg)->rgdb_keys[(rgdb)][(id)]))
|
||||
|
||||
static DWORD str_to_dword(const char *a) {
|
||||
int i;
|
||||
unsigned long ret = 0;
|
||||
for(i = strlen(a)-1; i >= 0; i--) {
|
||||
ret = ret * 0x100 + a[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0 /* unused */
|
||||
|
||||
static DWORD calc_hash(const char *str) {
|
||||
DWORD ret = 0;
|
||||
int i;
|
||||
for(i = 0; str[i] && str[i] != '\\'; i++) {
|
||||
ret+=toupper(str[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void parse_rgkn_block(CREG *creg, off_t start_off, off_t end_off)
|
||||
{
|
||||
off_t i;
|
||||
for(i = start_off; end_off - i > sizeof(RGKN_KEY); i+= sizeof(RGKN_KEY)) {
|
||||
RGKN_KEY *key = (RGKN_KEY *)LOCN_RGKN(creg, i);
|
||||
if(key->type == 0) {
|
||||
DEBUG(4,("Regular, id: %d, %d, parent: %x, firstchild: %x, next: %x hash: %lX\n", key->id.id, key->id.rgdb, key->parent_offset, key->first_child_offset, key->next_offset, (long)key->hash));
|
||||
} else if(key->type == 0x80000000) {
|
||||
DEBUG(3,("free\n"));
|
||||
i += key->hash;
|
||||
} else {
|
||||
DEBUG(0,("Invalid key type in RGKN: %0X\n", key->type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void parse_rgdb_block(CREG *creg, RGDB_HDR *rgdb_hdr)
|
||||
{
|
||||
DWORD used_size = rgdb_hdr->size - rgdb_hdr->unused_size;
|
||||
DWORD offset = 0;
|
||||
|
||||
while(offset < used_size) {
|
||||
RGDB_KEY *key = (RGDB_KEY *)(((char *)rgdb_hdr) + sizeof(RGDB_HDR) + offset);
|
||||
|
||||
if(!(key->id.id == 0xFFFF && key->id.rgdb == 0xFFFF))creg->rgdb_keys[key->id.rgdb][key->id.id] = key;
|
||||
offset += key->size;
|
||||
}
|
||||
}
|
||||
|
||||
static WERROR w95_open_reg (struct registry_hive *h, struct registry_key **root)
|
||||
{
|
||||
CREG *creg;
|
||||
DWORD creg_id, rgkn_id;
|
||||
DWORD i;
|
||||
DWORD offset;
|
||||
|
||||
creg = talloc(h, CREG);
|
||||
memset(creg, 0, sizeof(CREG));
|
||||
h->backend_data = creg;
|
||||
|
||||
if((creg->fd = open(h->location, O_RDONLY, 0000)) < 0) {
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
if (fstat(creg->fd, &creg->sbuf) < 0) {
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
creg->base = mmap(0, creg->sbuf.st_size, PROT_READ, MAP_SHARED, creg->fd, 0);
|
||||
|
||||
if (creg->base == (void *)-1) {
|
||||
DEBUG(0,("Could not mmap file: %s, %s\n", h->location, strerror(errno)));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
creg->creg_hdr = (CREG_HDR *)creg->base;
|
||||
|
||||
if ((creg_id = IVAL(&creg->creg_hdr->CREG_ID,0)) != str_to_dword("CREG")) {
|
||||
DEBUG(0, ("Unrecognized Windows 95 registry header id: 0x%0X, %s\n",
|
||||
creg_id, h->location));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
creg->rgkn_hdr = (RGKN_HDR *)LOCN_RGKN(creg, 0);
|
||||
|
||||
if ((rgkn_id = IVAL(&creg->rgkn_hdr->RGKN_ID,0)) != str_to_dword("RGKN")) {
|
||||
DEBUG(0, ("Unrecognized Windows 95 registry key index id: 0x%0X, %s\n",
|
||||
rgkn_id, h->location));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* If'ed out because we only need to parse this stuff when allocating new
|
||||
* entries (which we don't do at the moment */
|
||||
/* First parse the 0x2000 long block */
|
||||
parse_rgkn_block(creg, sizeof(RGKN_HDR), 0x2000);
|
||||
|
||||
/* Then parse the other 0x1000 length blocks */
|
||||
for(offset = 0x2000; offset < creg->rgkn_hdr->size; offset+=0x1000) {
|
||||
parse_rgkn_block(creg, offset, offset+0x1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
creg->rgdb_keys = talloc_array(h, RGDB_KEY **, creg->creg_hdr->num_rgdb);
|
||||
|
||||
offset = 0;
|
||||
DEBUG(3, ("Reading %d rgdb entries\n", creg->creg_hdr->num_rgdb));
|
||||
for(i = 0; i < creg->creg_hdr->num_rgdb; i++) {
|
||||
RGDB_HDR *rgdb_hdr = (RGDB_HDR *)LOCN_RGDB_BLOCK(creg, offset);
|
||||
|
||||
if(strncmp((char *)&(rgdb_hdr->RGDB_ID), "RGDB", 4)) {
|
||||
DEBUG(0, ("unrecognized rgdb entry: %4d, %s\n",
|
||||
rgdb_hdr->RGDB_ID, h->location));
|
||||
return WERR_FOOBAR;
|
||||
} else {
|
||||
DEBUG(3, ("Valid rgdb entry, first free id: %d, max id: %d\n", rgdb_hdr->first_free_id, rgdb_hdr->max_id));
|
||||
}
|
||||
|
||||
|
||||
creg->rgdb_keys[i] = talloc_array(h, RGDB_KEY *, rgdb_hdr->max_id+1);
|
||||
memset(creg->rgdb_keys[i], 0, sizeof(RGDB_KEY *) * (rgdb_hdr->max_id+1));
|
||||
|
||||
parse_rgdb_block(creg, rgdb_hdr);
|
||||
|
||||
offset+=rgdb_hdr->size;
|
||||
}
|
||||
|
||||
/* First element in rgkn should be root key */
|
||||
*root = talloc(h, struct registry_key);
|
||||
(*root)->name = NULL;
|
||||
(*root)->backend_data = LOCN_RGKN(creg, sizeof(RGKN_HDR));
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR w95_get_subkey_by_index (TALLOC_CTX *mem_ctx, const struct registry_key *parent, int n, struct registry_key **key)
|
||||
{
|
||||
CREG *creg = parent->hive->backend_data;
|
||||
RGKN_KEY *rgkn_key = parent->backend_data;
|
||||
RGKN_KEY *child;
|
||||
DWORD child_offset;
|
||||
DWORD cur = 0;
|
||||
|
||||
/* Get id of first child */
|
||||
child_offset = rgkn_key->first_child_offset;
|
||||
|
||||
while(child_offset != 0xFFFFFFFF) {
|
||||
child = LOCN_RGKN(creg, child_offset);
|
||||
|
||||
/* n == cur ? return! */
|
||||
if(cur == n) {
|
||||
RGDB_KEY *rgdb_key;
|
||||
rgdb_key = LOCN_RGDB_KEY(creg, child->id.rgdb, child->id.id);
|
||||
if(!rgdb_key) {
|
||||
DEBUG(0, ("Can't find %d,%d in RGDB table!\n", child->id.rgdb, child->id.id));
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
*key = talloc(mem_ctx, struct registry_key);
|
||||
(*key)->backend_data = child;
|
||||
(*key)->name = talloc_strndup(mem_ctx, (char *)rgdb_key + sizeof(RGDB_KEY), rgdb_key->name_len);
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
cur++;
|
||||
|
||||
child_offset = child->next_offset;
|
||||
}
|
||||
|
||||
return WERR_NO_MORE_ITEMS;
|
||||
}
|
||||
|
||||
static WERROR w95_num_values(const struct registry_key *k, uint32_t *count)
|
||||
{
|
||||
RGKN_KEY *rgkn_key = k->backend_data;
|
||||
RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id);
|
||||
|
||||
if(!rgdb_key) return WERR_FOOBAR;
|
||||
|
||||
*count = rgdb_key->num_values;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR w95_get_value_by_id(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_value **value)
|
||||
{
|
||||
RGKN_KEY *rgkn_key = k->backend_data;
|
||||
DWORD i;
|
||||
DWORD offset = 0;
|
||||
RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id);
|
||||
RGDB_VALUE *curval = NULL;
|
||||
|
||||
if(!rgdb_key) return WERR_FOOBAR;
|
||||
|
||||
if(idx >= rgdb_key->num_values) return WERR_NO_MORE_ITEMS;
|
||||
|
||||
for(i = 0; i < idx; i++) {
|
||||
curval = (RGDB_VALUE *)(((char *)rgdb_key) + sizeof(RGDB_KEY) + rgdb_key->name_len + offset);
|
||||
offset+=sizeof(RGDB_VALUE) + curval->name_len + curval->data_len;
|
||||
}
|
||||
|
||||
*value = talloc(mem_ctx, struct registry_value);
|
||||
(*value)->name = talloc_strndup(mem_ctx, (char *)curval+sizeof(RGDB_VALUE), curval->name_len);
|
||||
|
||||
(*value)->data = data_blob_talloc(mem_ctx, curval+sizeof(RGDB_VALUE)+curval->name_len, curval->data_len);
|
||||
(*value)->data_type = curval->type;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct hive_operations reg_backend_w95 = {
|
||||
.name = "w95",
|
||||
.open_hive = w95_open_reg,
|
||||
.get_value_by_index = w95_get_value_by_id,
|
||||
.num_values = w95_num_values,
|
||||
.get_subkey_by_index = w95_get_subkey_by_index,
|
||||
};
|
||||
|
||||
NTSTATUS registry_w95_init(void)
|
||||
{
|
||||
return registry_register(®_backend_w95);
|
||||
}
|
1923
source4/lib/registry/regf.c
Normal file
1923
source4/lib/registry/regf.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -45,8 +45,8 @@ interface regf
|
||||
uint32 data_offset;
|
||||
uint32 last_block;
|
||||
[value(1)] uint32 uk7; /* 1 */
|
||||
[charset(UTF16)] uint16 description[0x40];
|
||||
uint32 padding[83]; /* Padding */
|
||||
[charset(UTF16)] uint16 description[0x20];
|
||||
uint32 padding[99]; /* Padding */
|
||||
/* Checksum of first 0x200 bytes XOR-ed */
|
||||
uint32 chksum;
|
||||
};
|
||||
@ -66,7 +66,7 @@ interface regf
|
||||
uint8 data[offset_to_next-0x20];
|
||||
/* data is filled with:
|
||||
uint32 length;
|
||||
Negative if in used, positive otherwise
|
||||
Negative if in use, positive otherwise
|
||||
Always a multiple of 8
|
||||
uint8_t data[length];
|
||||
Free space marker if 0xffffffff
|
||||
|
@ -2,7 +2,7 @@
|
||||
Unix SMB/CIFS implementation.
|
||||
Registry interface
|
||||
Copyright (C) Gerald Carter 2002.
|
||||
Copyright (C) Jelmer Vernooij 2003-2004.
|
||||
Copyright (C) Jelmer Vernooij 2003-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
|
||||
@ -21,9 +21,12 @@
|
||||
#ifndef _REGISTRY_H /* _REGISTRY_H */
|
||||
#define _REGISTRY_H
|
||||
|
||||
struct registry_context;
|
||||
|
||||
#include "core.h"
|
||||
#include "talloc/talloc.h"
|
||||
#include "librpc/gen_ndr/security.h"
|
||||
#include "lib/registry/hive.h"
|
||||
|
||||
/* Handles for the predefined keys */
|
||||
#define HKEY_CLASSES_ROOT 0x80000000
|
||||
@ -36,6 +39,9 @@
|
||||
#define HKEY_PERFORMANCE_TEXT 0x80000050
|
||||
#define HKEY_PERFORMANCE_NLSTEXT 0x80000060
|
||||
|
||||
#define HKEY_FIRST HKEY_CLASSES_ROOT
|
||||
#define HKEY_LAST HKEY_PERFORMANCE_NLSTEXT
|
||||
|
||||
struct reg_predefined_key {
|
||||
uint32_t handle;
|
||||
const char *name;
|
||||
@ -52,17 +58,16 @@ extern const struct reg_predefined_key reg_predefined_keys[];
|
||||
|
||||
#define REGISTRY_INTERFACE_VERSION 1
|
||||
|
||||
struct reg_key_operations;
|
||||
|
||||
/* structure to store the registry handles */
|
||||
struct registry_key
|
||||
{
|
||||
const char *name;
|
||||
const char *path;
|
||||
const char *class_name;
|
||||
NTTIME last_mod;
|
||||
struct registry_hive *hive;
|
||||
void *backend_data;
|
||||
struct registry_context *context;
|
||||
};
|
||||
|
||||
#include "lib/registry/patchfile.h"
|
||||
|
||||
struct registry_value
|
||||
{
|
||||
const char *name;
|
||||
@ -74,109 +79,87 @@ struct registry_value
|
||||
typedef void (*reg_key_notification_function) (void);
|
||||
typedef void (*reg_value_notification_function) (void);
|
||||
|
||||
/*
|
||||
* Container for function pointers to enumeration routines
|
||||
* for virtual registry view
|
||||
*
|
||||
* Backends can provide :
|
||||
* - just one hive (example: nt4, w95)
|
||||
* - several hives (example: rpc).
|
||||
*
|
||||
* Backends should always do case-insensitive compares
|
||||
* (everything is case-insensitive but case-preserving,
|
||||
* just like the FS)
|
||||
*
|
||||
* There is no save function as all operations are expected to
|
||||
* be atomic.
|
||||
*/
|
||||
|
||||
struct hive_operations {
|
||||
const char *name;
|
||||
|
||||
/* Implement this one */
|
||||
WERROR (*open_hive) (struct registry_hive *, struct registry_key **);
|
||||
|
||||
/* Or this one */
|
||||
WERROR (*open_key) (TALLOC_CTX *, const struct registry_key *, const char *name, struct registry_key **);
|
||||
|
||||
WERROR (*num_subkeys) (const struct registry_key *, uint32_t *count);
|
||||
WERROR (*num_values) (const struct registry_key *, uint32_t *count);
|
||||
WERROR (*get_subkey_by_index) (TALLOC_CTX *, const struct registry_key *, int idx, struct registry_key **);
|
||||
|
||||
/* Can not contain more than one level */
|
||||
WERROR (*get_subkey_by_name) (TALLOC_CTX *, const struct registry_key *, const char *name, struct registry_key **);
|
||||
WERROR (*get_value_by_index) (TALLOC_CTX *, const struct registry_key *, int idx, struct registry_value **);
|
||||
|
||||
/* Can not contain more than one level */
|
||||
WERROR (*get_value_by_name) (TALLOC_CTX *, const struct registry_key *, const char *name, struct registry_value **);
|
||||
|
||||
/* Security control */
|
||||
WERROR (*key_get_sec_desc) (TALLOC_CTX *, const struct registry_key *, struct security_descriptor **);
|
||||
WERROR (*key_set_sec_desc) (const struct registry_key *, const struct security_descriptor *);
|
||||
|
||||
/* Notification */
|
||||
WERROR (*request_key_change_notify) (const struct registry_key *, reg_key_notification_function);
|
||||
WERROR (*request_value_change_notify) (const struct registry_value *, reg_value_notification_function);
|
||||
|
||||
/* Key management */
|
||||
WERROR (*add_key)(TALLOC_CTX *, const struct registry_key *, const char *name, uint32_t access_mask, struct security_descriptor *, struct registry_key **);
|
||||
WERROR (*del_key)(const struct registry_key *, const char *name);
|
||||
WERROR (*flush_key) (const struct registry_key *);
|
||||
|
||||
/* Value management */
|
||||
WERROR (*set_value)(const struct registry_key *, const char *name, uint32_t type, const DATA_BLOB data);
|
||||
WERROR (*del_value)(const struct registry_key *, const char *valname);
|
||||
};
|
||||
|
||||
struct cli_credentials;
|
||||
struct registry_context;
|
||||
|
||||
struct registry_hive
|
||||
{
|
||||
const struct hive_operations *functions;
|
||||
struct registry_key *root;
|
||||
struct auth_session_info *session_info;
|
||||
struct cli_credentials *credentials;
|
||||
void *backend_data;
|
||||
const char *location;
|
||||
};
|
||||
struct registry_operations {
|
||||
const char *name;
|
||||
|
||||
/* Handle to a full registry
|
||||
* contains zero or more hives */
|
||||
WERROR (*get_key_info) (TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key,
|
||||
const char **classname,
|
||||
uint32_t *numsubkeys,
|
||||
uint32_t *numvalues,
|
||||
NTTIME *last_change_time);
|
||||
|
||||
WERROR (*flush_key) (struct registry_key *key);
|
||||
|
||||
WERROR (*get_predefined_key) (const struct registry_context *ctx,
|
||||
uint32_t key_id,
|
||||
struct registry_key **key);
|
||||
|
||||
WERROR (*open_key) (TALLOC_CTX *mem_ctx,
|
||||
struct registry_key *parent,
|
||||
const char *path,
|
||||
struct registry_key **key);
|
||||
|
||||
WERROR (*create_key) (TALLOC_CTX *mem_ctx,
|
||||
struct registry_key *parent,
|
||||
const char *name,
|
||||
const char *key_class,
|
||||
struct security_descriptor *security,
|
||||
struct registry_key **key);
|
||||
|
||||
WERROR (*delete_key) (struct registry_key *key, const char *name);
|
||||
|
||||
WERROR (*delete_value) (struct registry_key *key, const char *name);
|
||||
|
||||
WERROR (*enum_key) (TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key, uint32_t idx,
|
||||
const char **name,
|
||||
const char **keyclass,
|
||||
NTTIME *last_changed_time);
|
||||
|
||||
WERROR (*enum_value) (TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key, uint32_t idx,
|
||||
const char **name,
|
||||
uint32_t *type,
|
||||
DATA_BLOB *data);
|
||||
|
||||
WERROR (*get_security) (TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key,
|
||||
struct security_descriptor **security);
|
||||
|
||||
WERROR (*set_security) (struct registry_key *key,
|
||||
const struct security_descriptor *security);
|
||||
|
||||
WERROR (*load_key) (struct registry_key *key,
|
||||
const char *key_name,
|
||||
const char *path);
|
||||
|
||||
WERROR (*unload_key) (struct registry_key *key, const char *name);
|
||||
|
||||
WERROR (*notify_value_change) (struct registry_key *key,
|
||||
reg_value_notification_function fn);
|
||||
|
||||
WERROR (*get_value) (TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key,
|
||||
const char *name,
|
||||
uint32_t *type,
|
||||
DATA_BLOB *data);
|
||||
|
||||
WERROR (*set_value) (struct registry_key *key,
|
||||
const char *name,
|
||||
uint32_t type,
|
||||
const DATA_BLOB data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle to a full registry
|
||||
* contains zero or more hives
|
||||
*/
|
||||
struct registry_context {
|
||||
void *backend_data;
|
||||
struct cli_credentials *credentials;
|
||||
struct auth_session_info *session_info;
|
||||
WERROR (*get_predefined_key) (struct registry_context *, uint32_t hkey, struct registry_key **);
|
||||
};
|
||||
|
||||
struct reg_init_function_entry {
|
||||
const struct hive_operations *hive_functions;
|
||||
struct reg_init_function_entry *prev, *next;
|
||||
};
|
||||
|
||||
/* Representing differences between registry files */
|
||||
|
||||
struct reg_diff_value
|
||||
{
|
||||
const char *name;
|
||||
enum { REG_DIFF_DEL_VAL, REG_DIFF_SET_VAL } changetype;
|
||||
uint32_t type;
|
||||
DATA_BLOB data;
|
||||
};
|
||||
|
||||
struct reg_diff_key
|
||||
{
|
||||
const char *name;
|
||||
enum { REG_DIFF_CHANGE_KEY, REG_DIFF_DEL_KEY } changetype;
|
||||
uint32_t numvalues;
|
||||
struct reg_diff_value *values;
|
||||
};
|
||||
|
||||
struct reg_diff
|
||||
{
|
||||
const char *format;
|
||||
uint32_t numkeys;
|
||||
struct reg_diff_key *keys;
|
||||
const struct registry_operations *ops;
|
||||
};
|
||||
|
||||
struct auth_session_info;
|
||||
@ -186,60 +169,110 @@ struct event_context;
|
||||
#define _PUBLIC_
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Open the locally defined registry.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_open_local (TALLOC_CTX *mem_ctx,
|
||||
struct registry_context **ctx,
|
||||
struct auth_session_info *session_info,
|
||||
struct cli_credentials *credentials);
|
||||
|
||||
_PUBLIC_ WERROR reg_open_samba (TALLOC_CTX *mem_ctx,
|
||||
struct registry_context **ctx,
|
||||
struct auth_session_info *session_info,
|
||||
struct cli_credentials *credentials);
|
||||
|
||||
/**
|
||||
* Open the registry on a remote machine.
|
||||
*/
|
||||
_PUBLIC_ WERROR reg_open_remote(struct registry_context **ctx,
|
||||
struct auth_session_info *session_info,
|
||||
struct cli_credentials *credentials,
|
||||
const char *location, struct event_context *ev);
|
||||
|
||||
_PUBLIC_ NTSTATUS registry_register(const void *_hive_ops);
|
||||
_PUBLIC_ NTSTATUS registry_init(void);
|
||||
_PUBLIC_ BOOL reg_has_backend(const char *backend);
|
||||
_PUBLIC_ int reg_list_predefs(TALLOC_CTX *mem_ctx, char ***predefs, uint32_t **hkeys);
|
||||
_PUBLIC_ WERROR reg_open_wine(struct registry_context **ctx, const char *path);
|
||||
|
||||
_PUBLIC_ const char *reg_get_predef_name(uint32_t hkey);
|
||||
_PUBLIC_ WERROR reg_get_predefined_key_by_name(struct registry_context *ctx, const char *name, struct registry_key **key);
|
||||
_PUBLIC_ WERROR reg_get_predefined_key(struct registry_context *ctx, uint32_t hkey, struct registry_key **key);
|
||||
_PUBLIC_ WERROR reg_open_hive(TALLOC_CTX *parent_ctx, const char *backend, const char *location, struct auth_session_info *session_info, struct cli_credentials *credentials, struct registry_key **root);
|
||||
_PUBLIC_ WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, struct registry_key **result);
|
||||
_PUBLIC_ WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *key, int idx, struct registry_value **val);
|
||||
_PUBLIC_ WERROR reg_key_num_subkeys(const struct registry_key *key, uint32_t *count);
|
||||
_PUBLIC_ WERROR reg_key_num_values(const struct registry_key *key, uint32_t *count);
|
||||
_PUBLIC_ WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *key, int idx, struct registry_key **subkey);
|
||||
WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, const struct registry_key *key, const char *name, struct registry_key **subkey);
|
||||
_PUBLIC_ WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, const struct registry_key *key, const char *name, struct registry_value **val);
|
||||
_PUBLIC_ WERROR reg_get_predefined_key_by_name(struct registry_context *ctx,
|
||||
const char *name,
|
||||
struct registry_key **key);
|
||||
_PUBLIC_ WERROR reg_get_predefined_key(const struct registry_context *ctx,
|
||||
uint32_t hkey,
|
||||
struct registry_key **key);
|
||||
|
||||
_PUBLIC_ WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent,
|
||||
const char *name, struct registry_key **result);
|
||||
|
||||
_PUBLIC_ WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key, uint32_t idx,
|
||||
const char **name,
|
||||
uint32_t *type,
|
||||
DATA_BLOB *data);
|
||||
_PUBLIC_ WERROR reg_key_get_info(TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key,
|
||||
const char **class_name,
|
||||
uint32_t *num_subkeys,
|
||||
uint32_t *num_values,
|
||||
NTTIME *last_change_time);
|
||||
_PUBLIC_ WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key,
|
||||
int idx,
|
||||
const char **name,
|
||||
const char **classname,
|
||||
NTTIME *last_mod_time);
|
||||
WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key,
|
||||
const char *name,
|
||||
struct registry_key **subkey);
|
||||
_PUBLIC_ WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *key,
|
||||
const char *name,
|
||||
uint32_t *type,
|
||||
DATA_BLOB *data);
|
||||
_PUBLIC_ WERROR reg_key_del(struct registry_key *parent, const char *name);
|
||||
_PUBLIC_ WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **newkey);
|
||||
_PUBLIC_ WERROR reg_val_set(struct registry_key *key, const char *value, uint32_t type, DATA_BLOB data);
|
||||
_PUBLIC_ WERROR reg_key_add_name(TALLOC_CTX *mem_ctx,
|
||||
struct registry_key *parent, const char *name,
|
||||
const char *classname,
|
||||
struct security_descriptor *desc,
|
||||
struct registry_key **newkey);
|
||||
_PUBLIC_ WERROR reg_val_set(struct registry_key *key, const char *value,
|
||||
uint32_t type, DATA_BLOB data);
|
||||
_PUBLIC_ WERROR reg_get_sec_desc(TALLOC_CTX *ctx, const struct registry_key *key, struct security_descriptor **secdesc);
|
||||
_PUBLIC_ WERROR reg_del_value(const struct registry_key *key, const char *valname);
|
||||
_PUBLIC_ WERROR reg_key_flush(const struct registry_key *key);
|
||||
_PUBLIC_ WERROR reg_key_subkeysizes(const struct registry_key *key, uint32_t *max_subkeylen, uint32_t *max_subkeysize);
|
||||
_PUBLIC_ WERROR reg_key_valuesizes(const struct registry_key *key, uint32_t *max_valnamelen, uint32_t *max_valbufsize);
|
||||
_PUBLIC_ WERROR reg_del_value(struct registry_key *key, const char *valname);
|
||||
_PUBLIC_ WERROR reg_key_flush(struct registry_key *key);
|
||||
WERROR reg_create_key (TALLOC_CTX *mem_ctx,
|
||||
struct registry_key *parent,
|
||||
|
||||
const char *name,
|
||||
const char *key_class,
|
||||
struct security_descriptor *security,
|
||||
struct registry_key **key);
|
||||
|
||||
|
||||
|
||||
|
||||
/* Utility functions */
|
||||
|
||||
_PUBLIC_ const char *str_regtype(int type);
|
||||
_PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type, DATA_BLOB *data);
|
||||
_PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx, struct registry_value *val) ;
|
||||
_PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type,
|
||||
const DATA_BLOB data);
|
||||
_PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx, const char *name,
|
||||
uint32_t type, const DATA_BLOB data);
|
||||
_PUBLIC_ BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *data_str, uint32_t *type, DATA_BLOB *data);
|
||||
char *reg_path_win2unix(char *path) ;
|
||||
char *reg_path_unix2win(char *path) ;
|
||||
WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result);
|
||||
WERROR reg_key_del_abs(struct registry_context *ctx, const char *path);
|
||||
WERROR reg_key_add_abs(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, uint32_t access_mask, struct security_descriptor *sec_desc, struct registry_key **result);
|
||||
WERROR reg_load_key(struct registry_context *ctx, struct registry_key *key,
|
||||
const char *name, const char *filename);
|
||||
|
||||
WERROR reg_mount_hive(struct registry_context *rctx,
|
||||
struct hive_key *hive_key,
|
||||
uint32_t key_id,
|
||||
const char **elements);
|
||||
|
||||
/* Patch files */
|
||||
struct registry_key *reg_import_hive_key(struct registry_context *ctx,
|
||||
struct hive_key *hive,
|
||||
uint32_t predef_key,
|
||||
const char **elements);
|
||||
|
||||
_PUBLIC_ struct reg_diff *reg_generate_diff(TALLOC_CTX *mem_ctx, struct registry_context *ctx1, struct registry_context *ctx2);
|
||||
_PUBLIC_ WERROR reg_diff_save(const struct reg_diff *diff, const char *filename);
|
||||
_PUBLIC_ struct reg_diff *reg_diff_load(TALLOC_CTX *ctx, const char *fn);
|
||||
_PUBLIC_ BOOL reg_diff_apply (const struct reg_diff *diff, struct registry_context *ctx);
|
||||
|
||||
NTSTATUS registry_rpc_init(void);
|
||||
|
||||
#endif /* _REGISTRY_H */
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
Samba Unix/Linux SMB implementation
|
||||
RPC backend for the registry library
|
||||
Copyright (C) 2003-2004 Jelmer Vernooij, jelmer@samba.org
|
||||
Copyright (C) 2003-2007 Jelmer Vernooij, jelmer@samba.org
|
||||
|
||||
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
|
||||
@ -20,7 +20,23 @@
|
||||
#include "registry.h"
|
||||
#include "librpc/gen_ndr/ndr_winreg_c.h"
|
||||
|
||||
static struct hive_operations reg_backend_rpc;
|
||||
struct rpc_key {
|
||||
struct registry_key key;
|
||||
struct policy_handle pol;
|
||||
struct dcerpc_pipe *pipe;
|
||||
|
||||
uint32_t num_values;
|
||||
uint32_t num_subkeys;
|
||||
uint32_t max_valnamelen;
|
||||
uint32_t max_valdatalen;
|
||||
};
|
||||
|
||||
struct rpc_registry_context {
|
||||
struct registry_context context;
|
||||
struct dcerpc_pipe *pipe;
|
||||
};
|
||||
|
||||
static struct registry_operations reg_backend_rpc;
|
||||
|
||||
/**
|
||||
* This is the RPC backend for the registry library.
|
||||
@ -58,57 +74,46 @@ openhive(HKCR)
|
||||
openhive(HKDD)
|
||||
openhive(HKCC)
|
||||
|
||||
struct rpc_key_data {
|
||||
struct policy_handle pol;
|
||||
int num_subkeys;
|
||||
int num_values;
|
||||
int max_valnamelen;
|
||||
int max_valdatalen;
|
||||
};
|
||||
|
||||
static struct {
|
||||
uint32_t hkey;
|
||||
WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *, struct policy_handle *h);
|
||||
} known_hives[] = {
|
||||
{ HKEY_LOCAL_MACHINE, open_HKLM },
|
||||
{ HKEY_CURRENT_USER, open_HKCU },
|
||||
{ HKEY_CLASSES_ROOT, open_HKCR },
|
||||
{ HKEY_PERFORMANCE_DATA, open_HKPD },
|
||||
{ HKEY_USERS, open_HKU },
|
||||
{ HKEY_DYN_DATA, open_HKDD },
|
||||
{ HKEY_CURRENT_CONFIG, open_HKCC },
|
||||
{ 0, NULL }
|
||||
{ HKEY_LOCAL_MACHINE, open_HKLM },
|
||||
{ HKEY_CURRENT_USER, open_HKCU },
|
||||
{ HKEY_CLASSES_ROOT, open_HKCR },
|
||||
{ HKEY_PERFORMANCE_DATA, open_HKPD },
|
||||
{ HKEY_USERS, open_HKU },
|
||||
{ HKEY_DYN_DATA, open_HKDD },
|
||||
{ HKEY_CURRENT_CONFIG, open_HKCC },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static WERROR rpc_query_key(const struct registry_key *k);
|
||||
|
||||
static WERROR rpc_get_predefined_key (struct registry_context *ctx, uint32_t hkey_type, struct registry_key **k)
|
||||
static WERROR rpc_get_predefined_key(struct registry_context *ctx,
|
||||
uint32_t hkey_type,
|
||||
struct registry_key **k)
|
||||
{
|
||||
int n;
|
||||
struct registry_hive *h;
|
||||
struct rpc_key_data *mykeydata;
|
||||
struct rpc_registry_context *rctx = talloc_get_type(ctx,
|
||||
struct rpc_registry_context);
|
||||
struct rpc_key *mykeydata;
|
||||
|
||||
for(n = 0; known_hives[n].hkey; n++)
|
||||
{
|
||||
if(known_hives[n].hkey == hkey_type) break;
|
||||
for(n = 0; known_hives[n].hkey; n++) {
|
||||
if(known_hives[n].hkey == hkey_type)
|
||||
break;
|
||||
}
|
||||
|
||||
if(!known_hives[n].open) {
|
||||
if (known_hives[n].open == NULL) {
|
||||
DEBUG(1, ("No such hive %d\n", hkey_type));
|
||||
return WERR_NO_MORE_ITEMS;
|
||||
}
|
||||
|
||||
h = talloc(ctx, struct registry_hive);
|
||||
h->functions = ®_backend_rpc;
|
||||
h->location = NULL;
|
||||
h->backend_data = ctx->backend_data;
|
||||
|
||||
(*k) = h->root = talloc(h, struct registry_key);
|
||||
(*k)->hive = h;
|
||||
(*k)->backend_data = mykeydata = talloc(*k, struct rpc_key_data);
|
||||
mykeydata = talloc(ctx, struct rpc_key);
|
||||
mykeydata->pipe = rctx->pipe;
|
||||
mykeydata->num_values = -1;
|
||||
mykeydata->num_subkeys = -1;
|
||||
return known_hives[n].open((struct dcerpc_pipe *)ctx->backend_data, *k, &(mykeydata->pol));
|
||||
return known_hives[n].open(mykeydata->pipe, *k, &(mykeydata->pol));
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -136,44 +141,44 @@ static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k)
|
||||
}
|
||||
#endif
|
||||
|
||||
static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, const struct registry_key *h, const char *name, struct registry_key **key)
|
||||
static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h,
|
||||
const char *name, struct registry_key **key)
|
||||
{
|
||||
struct rpc_key_data *mykeydata;
|
||||
struct rpc_key *mykeydata = talloc_get_type(h, struct rpc_key),
|
||||
*newkeydata;
|
||||
struct winreg_OpenKey r;
|
||||
|
||||
*key = talloc(mem_ctx, struct registry_key);
|
||||
(*key)->name = talloc_strdup(mem_ctx, name);
|
||||
|
||||
(*key)->backend_data = mykeydata = talloc(mem_ctx, struct rpc_key_data);
|
||||
mykeydata->num_values = -1;
|
||||
mykeydata->num_subkeys = -1;
|
||||
mykeydata = talloc(mem_ctx, struct rpc_key);
|
||||
|
||||
/* Then, open the handle using the hive */
|
||||
|
||||
memset(&r, 0, sizeof(struct winreg_OpenKey));
|
||||
r.in.parent_handle = &(((struct rpc_key_data *)h->backend_data)->pol);
|
||||
r.in.parent_handle = &mykeydata->pol;
|
||||
init_winreg_String(&r.in.keyname, name);
|
||||
r.in.unknown = 0x00000000;
|
||||
r.in.access_mask = 0x02000000;
|
||||
r.out.handle = &mykeydata->pol;
|
||||
r.out.handle = &newkeydata->pol;
|
||||
|
||||
dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(h->hive->backend_data), mem_ctx, &r);
|
||||
dcerpc_winreg_OpenKey(mykeydata->pipe, mem_ctx, &r);
|
||||
|
||||
return r.out.result;
|
||||
}
|
||||
|
||||
static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *parent, int n, struct registry_value **value)
|
||||
static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *parent,
|
||||
uint32_t n,
|
||||
const char **value_name,
|
||||
uint32_t *type,
|
||||
DATA_BLOB *data)
|
||||
{
|
||||
struct rpc_key_data *mykeydata = parent->backend_data;
|
||||
struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key);
|
||||
WERROR error;
|
||||
struct winreg_EnumValue r;
|
||||
uint32_t len1, zero = 0;
|
||||
enum winreg_Type type;
|
||||
NTSTATUS status;
|
||||
struct winreg_StringBuf name;
|
||||
uint8_t u8;
|
||||
|
||||
if(mykeydata->num_values == -1) {
|
||||
if (mykeydata->num_values == -1) {
|
||||
error = rpc_query_key(parent);
|
||||
if(!W_ERROR_IS_OK(error)) return error;
|
||||
}
|
||||
@ -187,13 +192,13 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, const struct registry_
|
||||
r.in.handle = &mykeydata->pol;
|
||||
r.in.enum_index = n;
|
||||
r.in.name = &name;
|
||||
r.in.type = &type;
|
||||
r.in.type = type;
|
||||
r.in.value = &u8;
|
||||
r.in.length = &zero;
|
||||
r.in.size = &len1;
|
||||
r.out.name = &name;
|
||||
|
||||
status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r);
|
||||
status = dcerpc_winreg_EnumValue(mykeydata->pipe, mem_ctx, &r);
|
||||
if(NT_STATUS_IS_ERR(status)) {
|
||||
DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status)));
|
||||
return WERR_GENERAL_FAILURE;
|
||||
@ -201,20 +206,23 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, const struct registry_
|
||||
|
||||
if(NT_STATUS_IS_OK(status) &&
|
||||
W_ERROR_IS_OK(r.out.result) && r.out.length) {
|
||||
*value = talloc(mem_ctx, struct registry_value);
|
||||
(*value)->name = talloc_strdup(mem_ctx, r.out.name->name);
|
||||
(*value)->data_type = type;
|
||||
(*value)->data = data_blob_talloc(mem_ctx, r.out.value, *r.out.length);
|
||||
*value_name = talloc_strdup(mem_ctx, r.out.name->name);
|
||||
*data = data_blob_talloc(mem_ctx, r.out.value, *r.out.length);
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
return r.out.result;
|
||||
}
|
||||
|
||||
static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *parent, int n, struct registry_key **subkey)
|
||||
static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx,
|
||||
const struct registry_key *parent,
|
||||
uint32_t n,
|
||||
const char **name,
|
||||
const char **keyclass,
|
||||
NTTIME *last_changed_time)
|
||||
{
|
||||
struct winreg_EnumKey r;
|
||||
struct rpc_key_data *mykeydata = parent->backend_data;
|
||||
struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key);
|
||||
NTSTATUS status;
|
||||
struct winreg_StringBuf namebuf, classbuf;
|
||||
NTTIME change_time = 0;
|
||||
@ -233,40 +241,47 @@ static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, const struct registry
|
||||
r.in.last_changed_time = &change_time;
|
||||
r.out.name = &namebuf;
|
||||
|
||||
status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r);
|
||||
status = dcerpc_winreg_EnumKey(mykeydata->pipe, mem_ctx, &r);
|
||||
if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
|
||||
char *name = talloc_strdup(mem_ctx, r.out.name->name);
|
||||
return rpc_open_key(mem_ctx, parent, name, subkey);
|
||||
*name = talloc_strdup(mem_ctx, r.out.name->name);
|
||||
*keyclass = talloc_strdup(mem_ctx, r.out.keyclass->name);
|
||||
*last_changed_time = *r.out.last_changed_time;
|
||||
}
|
||||
|
||||
return r.out.result;
|
||||
}
|
||||
|
||||
static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sec, struct registry_key **key)
|
||||
static WERROR rpc_add_key(TALLOC_CTX *mem_ctx,
|
||||
struct registry_key *parent, const char *name,
|
||||
const char *key_class,
|
||||
struct security_descriptor *sec,
|
||||
struct registry_key **key)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct winreg_CreateKey r;
|
||||
struct rpc_key *parentkd = talloc_get_type(parent, struct rpc_key);
|
||||
struct rpc_key *rpck = talloc(mem_ctx, struct rpc_key);
|
||||
|
||||
init_winreg_String(&r.in.name, name);
|
||||
init_winreg_String(&r.in.keyclass, NULL);
|
||||
|
||||
r.in.handle = parent->backend_data;
|
||||
r.out.new_handle = talloc(mem_ctx, struct policy_handle);
|
||||
r.in.handle = &parentkd->pol;
|
||||
r.out.new_handle = &rpck->pol;
|
||||
r.in.options = 0;
|
||||
r.in.access_mask = access_mask;
|
||||
r.in.access_mask = SEC_STD_ALL;
|
||||
r.in.secdesc = NULL;
|
||||
|
||||
status = dcerpc_winreg_CreateKey((struct dcerpc_pipe *)(parent->hive->backend_data), mem_ctx, &r);
|
||||
status = dcerpc_winreg_CreateKey(parentkd->pipe, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(rpck);
|
||||
DEBUG(1, ("CreateKey failed - %s\n", nt_errstr(status)));
|
||||
return ntstatus_to_werror(status);
|
||||
}
|
||||
|
||||
if (W_ERROR_IS_OK(r.out.result)) {
|
||||
*key = talloc(mem_ctx, struct registry_key);
|
||||
(*key)->name = talloc_strdup(*key, name);
|
||||
(*key)->backend_data = r.out.new_handle;
|
||||
rpck->pipe = talloc_reference(rpck, parentkd->pipe);
|
||||
*key = (struct registry_key *)rpck;
|
||||
}
|
||||
|
||||
return r.out.result;
|
||||
@ -276,14 +291,14 @@ static WERROR rpc_query_key(const struct registry_key *k)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct winreg_QueryInfoKey r;
|
||||
struct rpc_key_data *mykeydata = k->backend_data;
|
||||
struct rpc_key *mykeydata = talloc_get_type(k, struct rpc_key);
|
||||
TALLOC_CTX *mem_ctx = talloc_init("query_key");
|
||||
|
||||
r.in.classname = talloc(mem_ctx, struct winreg_String);
|
||||
init_winreg_String(r.in.classname, NULL);
|
||||
r.in.handle = &mykeydata->pol;
|
||||
|
||||
status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)(k->hive->backend_data), mem_ctx, &r);
|
||||
status = dcerpc_winreg_QueryInfoKey(mykeydata->pipe, mem_ctx, &r);
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
@ -301,26 +316,29 @@ static WERROR rpc_query_key(const struct registry_key *k)
|
||||
return r.out.result;
|
||||
}
|
||||
|
||||
static WERROR rpc_del_key(const struct registry_key *parent, const char *name)
|
||||
static WERROR rpc_del_key(struct registry_key *parent, const char *name)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct rpc_key_data *mykeydata = parent->backend_data;
|
||||
struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key);
|
||||
struct winreg_DeleteKey r;
|
||||
TALLOC_CTX *mem_ctx = talloc_init("del_key");
|
||||
|
||||
r.in.handle = &mykeydata->pol;
|
||||
init_winreg_String(&r.in.key, name);
|
||||
|
||||
status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r);
|
||||
status = dcerpc_winreg_DeleteKey(mykeydata->pipe, mem_ctx, &r);
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return r.out.result;
|
||||
}
|
||||
|
||||
static WERROR rpc_num_values(const struct registry_key *key, uint32_t *count)
|
||||
static WERROR rpc_get_info(TALLOC_CTX *mem_ctx, const struct registry_key *key,
|
||||
const char **classname,
|
||||
uint32_t *numsubkeys,
|
||||
uint32_t *numvalue)
|
||||
{
|
||||
struct rpc_key_data *mykeydata = key->backend_data;
|
||||
struct rpc_key *mykeydata = talloc_get_type(key, struct rpc_key);
|
||||
WERROR error;
|
||||
|
||||
if(mykeydata->num_values == -1) {
|
||||
@ -328,42 +346,34 @@ static WERROR rpc_num_values(const struct registry_key *key, uint32_t *count)
|
||||
if(!W_ERROR_IS_OK(error)) return error;
|
||||
}
|
||||
|
||||
*count = mykeydata->num_values;
|
||||
/* FIXME: *classname = talloc_strdup(mem_ctx, mykeydata->classname); */
|
||||
*numvalue = mykeydata->num_values;
|
||||
*numsubkeys = mykeydata->num_subkeys;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR rpc_num_subkeys(const struct registry_key *key, uint32_t *count)
|
||||
{
|
||||
struct rpc_key_data *mykeydata = key->backend_data;
|
||||
WERROR error;
|
||||
|
||||
if(mykeydata->num_subkeys == -1) {
|
||||
error = rpc_query_key(key);
|
||||
if(!W_ERROR_IS_OK(error)) return error;
|
||||
}
|
||||
|
||||
*count = mykeydata->num_subkeys;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct hive_operations reg_backend_rpc = {
|
||||
static struct registry_operations reg_backend_rpc = {
|
||||
.name = "rpc",
|
||||
.open_key = rpc_open_key,
|
||||
.get_subkey_by_index = rpc_get_subkey_by_index,
|
||||
.get_value_by_index = rpc_get_value_by_index,
|
||||
.add_key = rpc_add_key,
|
||||
.del_key = rpc_del_key,
|
||||
.num_subkeys = rpc_num_subkeys,
|
||||
.num_values = rpc_num_values,
|
||||
.enum_key = rpc_get_subkey_by_index,
|
||||
.enum_value = rpc_get_value_by_index,
|
||||
.create_key = rpc_add_key,
|
||||
.delete_key = rpc_del_key,
|
||||
.get_key_info = rpc_get_info,
|
||||
};
|
||||
|
||||
_PUBLIC_ WERROR reg_open_remote(struct registry_context **ctx, struct auth_session_info *session_info, struct cli_credentials *credentials,
|
||||
const char *location, struct event_context *ev)
|
||||
_PUBLIC_ WERROR reg_open_remote(struct registry_context **ctx,
|
||||
struct auth_session_info *session_info,
|
||||
struct cli_credentials *credentials,
|
||||
const char *location, struct event_context *ev)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
struct rpc_registry_context *rctx;
|
||||
|
||||
*ctx = talloc(NULL, struct registry_context);
|
||||
dcerpc_init();
|
||||
|
||||
rctx = talloc(NULL, struct rpc_registry_context);
|
||||
|
||||
/* Default to local smbd if no connection is specified */
|
||||
if (!location) {
|
||||
@ -374,7 +384,7 @@ _PUBLIC_ WERROR reg_open_remote(struct registry_context **ctx, struct auth_sessi
|
||||
&p, location,
|
||||
&ndr_table_winreg,
|
||||
credentials, ev);
|
||||
(*ctx)->backend_data = p;
|
||||
rctx->pipe = p;
|
||||
|
||||
if(NT_STATUS_IS_ERR(status)) {
|
||||
DEBUG(1, ("Unable to open '%s': %s\n", location, nt_errstr(status)));
|
||||
@ -383,13 +393,7 @@ _PUBLIC_ WERROR reg_open_remote(struct registry_context **ctx, struct auth_sessi
|
||||
return ntstatus_to_werror(status);
|
||||
}
|
||||
|
||||
(*ctx)->get_predefined_key = rpc_get_predefined_key;
|
||||
*ctx = (struct registry_context *)rctx;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
NTSTATUS registry_rpc_init(void)
|
||||
{
|
||||
dcerpc_init();
|
||||
return registry_register(®_backend_rpc);
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Copyright (C) Jelmer Vernooij 2004.
|
||||
Copyright (C) Jelmer Vernooij 2004-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
|
||||
@ -24,30 +24,51 @@
|
||||
* @brief Samba-specific registry functions
|
||||
*/
|
||||
|
||||
static WERROR reg_samba_get_predef (struct registry_context *ctx, uint32_t hkey, struct registry_key **k)
|
||||
WERROR mount_samba_hive(struct registry_context *ctx,
|
||||
struct auth_session_info *auth_info,
|
||||
struct cli_credentials *creds,
|
||||
const char *name,
|
||||
uint32_t hive_id)
|
||||
{
|
||||
WERROR error;
|
||||
const char *conf;
|
||||
char *backend;
|
||||
struct hive_key *hive;
|
||||
const char *location;
|
||||
const char *hivename = reg_get_predef_name(hkey);
|
||||
|
||||
*k = NULL;
|
||||
location = talloc_asprintf(ctx, "%s/%s.ldb", lp_private_dir(), name);
|
||||
|
||||
conf = lp_parm_string(-1, "registry", hivename);
|
||||
|
||||
if (!conf) {
|
||||
return WERR_NOT_SUPPORTED;
|
||||
error = reg_open_hive(ctx, location, auth_info, creds, &hive);
|
||||
if (!W_ERROR_IS_OK(error))
|
||||
return error;
|
||||
|
||||
return reg_mount_hive(ctx, hive, hive_id, NULL);
|
||||
}
|
||||
|
||||
|
||||
_PUBLIC_ WERROR reg_open_samba (TALLOC_CTX *mem_ctx,
|
||||
struct registry_context **ctx,
|
||||
struct auth_session_info *session_info,
|
||||
struct cli_credentials *credentials)
|
||||
{
|
||||
WERROR result;
|
||||
|
||||
result = reg_open_local(mem_ctx, ctx, session_info, credentials);
|
||||
if (!W_ERROR_IS_OK(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
location = strchr(conf, ':');
|
||||
if (location) {
|
||||
backend = talloc_strndup(ctx, conf, (int)(location - conf));
|
||||
location++;
|
||||
} else {
|
||||
backend = talloc_strdup(ctx, "ldb");
|
||||
location = conf;
|
||||
}
|
||||
mount_samba_hive(*ctx, session_info, credentials,
|
||||
"hklm", HKEY_LOCAL_MACHINE);
|
||||
|
||||
mount_samba_hive(*ctx, session_info, credentials,
|
||||
"hkcr", HKEY_CLASSES_ROOT);
|
||||
|
||||
/* FIXME: Should be mounted from NTUSER.DAT in the home directory of the
|
||||
* current user */
|
||||
mount_samba_hive(*ctx, session_info, credentials,
|
||||
"hkcu", HKEY_CURRENT_USER);
|
||||
|
||||
mount_samba_hive(*ctx, session_info, credentials,
|
||||
"hku", HKEY_USERS);
|
||||
|
||||
/* FIXME: Different hive backend for HKEY_CLASSES_ROOT: merged view of HKEY_LOCAL_MACHINE\Software\Classes
|
||||
* and HKEY_CURRENT_USER\Software\Classes */
|
||||
@ -59,23 +80,6 @@ static WERROR reg_samba_get_predef (struct registry_context *ctx, uint32_t hkey,
|
||||
/* FIXME: HKEY_LOCAL_MACHINE\Hardware is autogenerated */
|
||||
|
||||
/* FIXME: HKEY_LOCAL_MACHINE\Security\SAM is an alias for HKEY_LOCAL_MACHINE\SAM */
|
||||
|
||||
error = reg_open_hive(ctx, backend, location, ctx->session_info, ctx->credentials, k);
|
||||
|
||||
talloc_free(backend);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
_PUBLIC_ WERROR reg_open_local (TALLOC_CTX *mem_ctx,
|
||||
struct registry_context **ctx,
|
||||
struct auth_session_info *session_info,
|
||||
struct cli_credentials *credentials)
|
||||
{
|
||||
*ctx = talloc(mem_ctx, struct registry_context);
|
||||
(*ctx)->credentials = talloc_reference(*ctx, credentials);
|
||||
(*ctx)->session_info = talloc_reference(*ctx, session_info);
|
||||
(*ctx)->get_predefined_key = reg_samba_get_predef;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
105
source4/lib/registry/tests/diff.c
Normal file
105
source4/lib/registry/tests/diff.c
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
local testing of registry diff functionality
|
||||
|
||||
Copyright (C) Jelmer Vernooij 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 "lib/registry/registry.h"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/winreg.h"
|
||||
|
||||
static bool test_generate_diff(struct torture_context *test)
|
||||
{
|
||||
/* WERROR reg_generate_diff(struct registry_context *ctx1,
|
||||
struct registry_context *ctx2,
|
||||
const struct reg_diff_callbacks *callbacks,
|
||||
void *callback_data)
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool test_diff_load(struct torture_context *test)
|
||||
{
|
||||
/* WERROR reg_diff_load(const char *filename, const struct reg_diff_callbacks *callbacks, void *callback_data) */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_diff_apply(struct torture_context *test)
|
||||
{
|
||||
/*
|
||||
_PUBLIC_ WERROR reg_diff_apply (const char *filename, struct registry_context *ctx)
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *added_key = NULL;
|
||||
|
||||
static WERROR test_add_key (void *callback_data, const char *key_name)
|
||||
{
|
||||
added_key = talloc_strdup(callback_data, key_name);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static bool test_generate_diff_key_add(struct torture_context *test)
|
||||
{
|
||||
struct reg_diff_callbacks cb;
|
||||
struct registry_key rk;
|
||||
|
||||
return true;
|
||||
|
||||
ZERO_STRUCT(cb);
|
||||
|
||||
cb.add_key = test_add_key;
|
||||
|
||||
if (W_ERROR_IS_OK(reg_generate_diff_key(&rk, NULL, "bla", &cb, test)))
|
||||
return false;
|
||||
|
||||
torture_assert_str_equal(test, added_key, "bla", "key added");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_generate_diff_key_null(struct torture_context *test)
|
||||
{
|
||||
struct reg_diff_callbacks cb;
|
||||
|
||||
ZERO_STRUCT(cb);
|
||||
|
||||
if (!W_ERROR_IS_OK(reg_generate_diff_key(NULL, NULL, "", &cb, NULL)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct torture_suite *torture_registry_diff(TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct torture_suite *suite = torture_suite_create(mem_ctx,
|
||||
"DIFF");
|
||||
torture_suite_add_simple_test(suite, "test_generate_diff_key_add", test_generate_diff_key_add);
|
||||
torture_suite_add_simple_test(suite, "test_generate_diff_key_null", test_generate_diff_key_null);
|
||||
torture_suite_add_simple_test(suite, "test_diff_apply", test_diff_apply);
|
||||
torture_suite_add_simple_test(suite, "test_generate_diff", test_generate_diff);
|
||||
torture_suite_add_simple_test(suite, "test_diff_load", test_diff_load);
|
||||
return suite;
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
|
||||
local testing of registry library
|
||||
|
||||
Copyright (C) Jelmer Vernooij 2005
|
||||
Copyright (C) Jelmer Vernooij 2005-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
|
||||
@ -25,6 +25,10 @@
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/winreg.h"
|
||||
|
||||
struct torture_suite *torture_registry_hive(TALLOC_CTX *mem_ctx);
|
||||
struct torture_suite *torture_registry_registry(TALLOC_CTX *mem_ctx);
|
||||
struct torture_suite *torture_registry_diff(TALLOC_CTX *mem_ctx);
|
||||
|
||||
static bool test_str_regtype(struct torture_context *ctx)
|
||||
{
|
||||
torture_assert_str_equal(ctx, str_regtype(1), "REG_SZ", "REG_SZ failed");
|
||||
@ -38,7 +42,8 @@ static bool test_reg_val_data_string_dword(struct torture_context *ctx)
|
||||
{
|
||||
uint32_t d = 0x20;
|
||||
DATA_BLOB db = { (uint8_t *)&d, sizeof(d) };
|
||||
torture_assert_str_equal(ctx, "0x20", reg_val_data_string(ctx, REG_DWORD, &db), "dword failed");
|
||||
torture_assert_str_equal(ctx, "0x20",
|
||||
reg_val_data_string(ctx, REG_DWORD, db), "dword failed");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -46,9 +51,9 @@ static bool test_reg_val_data_string_sz(struct torture_context *ctx)
|
||||
{
|
||||
DATA_BLOB db;
|
||||
db.length = convert_string_talloc(ctx, CH_UNIX, CH_UTF16, "bla", 3, (void **)&db.data);
|
||||
torture_assert_str_equal(ctx, "bla", reg_val_data_string(ctx, REG_SZ, &db), "sz failed");
|
||||
torture_assert_str_equal(ctx, "bla", reg_val_data_string(ctx, REG_SZ, db), "sz failed");
|
||||
db.length = 4;
|
||||
torture_assert_str_equal(ctx, "bl", reg_val_data_string(ctx, REG_SZ, &db), "sz failed");
|
||||
torture_assert_str_equal(ctx, "bl", reg_val_data_string(ctx, REG_SZ, db), "sz failed");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -56,7 +61,9 @@ static bool test_reg_val_data_string_binary(struct torture_context *ctx)
|
||||
{
|
||||
uint8_t x[] = { 0x1, 0x2, 0x3, 0x4 };
|
||||
DATA_BLOB db = { x, 4 };
|
||||
torture_assert_str_equal(ctx, "01020304", reg_val_data_string(ctx, REG_BINARY, &db), "binary failed");
|
||||
torture_assert_str_equal(ctx, "01020304",
|
||||
reg_val_data_string(ctx, REG_BINARY, db),
|
||||
"binary failed");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -64,18 +71,20 @@ static bool test_reg_val_data_string_binary(struct torture_context *ctx)
|
||||
static bool test_reg_val_data_string_empty(struct torture_context *ctx)
|
||||
{
|
||||
DATA_BLOB db = { NULL, 0 };
|
||||
torture_assert_str_equal(ctx, "", reg_val_data_string(ctx, REG_BINARY, &db), "empty failed");
|
||||
torture_assert_str_equal(ctx, "",
|
||||
reg_val_data_string(ctx, REG_BINARY, db), "empty failed");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_reg_val_description(struct torture_context *ctx)
|
||||
{
|
||||
struct registry_value val;
|
||||
val.name = "camel";
|
||||
val.data_type = REG_SZ;
|
||||
val.data.length = convert_string_talloc(ctx, CH_UNIX, CH_UTF16, "stationary traveller",
|
||||
strlen("stationary traveller"), (void **)&val.data.data);
|
||||
torture_assert_str_equal(ctx, "camel = REG_SZ : stationary traveller", reg_val_description(ctx, &val),
|
||||
DATA_BLOB data;
|
||||
data.length = convert_string_talloc(ctx, CH_UNIX, CH_UTF16,
|
||||
"stationary traveller",
|
||||
strlen("stationary traveller"),
|
||||
(void **)&data.data);
|
||||
torture_assert_str_equal(ctx, "camel = REG_SZ : stationary traveller",
|
||||
reg_val_description(ctx, "camel", REG_SZ, data),
|
||||
"reg_val_description failed");
|
||||
return true;
|
||||
}
|
||||
@ -83,12 +92,11 @@ static bool test_reg_val_description(struct torture_context *ctx)
|
||||
|
||||
static bool test_reg_val_description_nullname(struct torture_context *ctx)
|
||||
{
|
||||
struct registry_value val;
|
||||
val.name = NULL;
|
||||
val.data_type = REG_SZ;
|
||||
val.data.length = convert_string_talloc(ctx, CH_UNIX, CH_UTF16, "west berlin",
|
||||
strlen("west berlin"), (void **)&val.data.data);
|
||||
torture_assert_str_equal(ctx, "<No Name> = REG_SZ : west berlin", reg_val_description(ctx, &val),
|
||||
DATA_BLOB data;
|
||||
data.length = convert_string_talloc(ctx, CH_UNIX, CH_UTF16, "west berlin",
|
||||
strlen("west berlin"), (void **)&data.data);
|
||||
torture_assert_str_equal(ctx, "<No Name> = REG_SZ : west berlin",
|
||||
reg_val_description(ctx, NULL, REG_SZ, data),
|
||||
"description with null name failed");
|
||||
return true;
|
||||
}
|
||||
@ -98,12 +106,22 @@ struct torture_suite *torture_registry(TALLOC_CTX *mem_ctx)
|
||||
struct torture_suite *suite = torture_suite_create(mem_ctx,
|
||||
"REGISTRY");
|
||||
torture_suite_add_simple_test(suite, "str_regtype", test_str_regtype);
|
||||
torture_suite_add_simple_test(suite, "reg_val_data_string dword", test_reg_val_data_string_dword);
|
||||
torture_suite_add_simple_test(suite, "reg_val_data_string sz", test_reg_val_data_string_sz);
|
||||
torture_suite_add_simple_test(suite, "reg_val_data_string binary", test_reg_val_data_string_binary);
|
||||
torture_suite_add_simple_test(suite, "reg_val_data_string empty", test_reg_val_data_string_empty);
|
||||
torture_suite_add_simple_test(suite, "reg_val_description", test_reg_val_description);
|
||||
torture_suite_add_simple_test(suite, "reg_val_description null", test_reg_val_description_nullname);
|
||||
torture_suite_add_simple_test(suite, "reg_val_data_string dword",
|
||||
test_reg_val_data_string_dword);
|
||||
torture_suite_add_simple_test(suite, "reg_val_data_string sz",
|
||||
test_reg_val_data_string_sz);
|
||||
torture_suite_add_simple_test(suite, "reg_val_data_string binary",
|
||||
test_reg_val_data_string_binary);
|
||||
torture_suite_add_simple_test(suite, "reg_val_data_string empty",
|
||||
test_reg_val_data_string_empty);
|
||||
torture_suite_add_simple_test(suite, "reg_val_description",
|
||||
test_reg_val_description);
|
||||
torture_suite_add_simple_test(suite, "reg_val_description null",
|
||||
test_reg_val_description_nullname);
|
||||
|
||||
torture_suite_add_suite(suite, torture_registry_hive(mem_ctx));
|
||||
torture_suite_add_suite(suite, torture_registry_registry(mem_ctx));
|
||||
torture_suite_add_suite(suite, torture_registry_diff(mem_ctx));
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
383
source4/lib/registry/tests/hive.c
Normal file
383
source4/lib/registry/tests/hive.c
Normal file
@ -0,0 +1,383 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
local testing of registry library - hives
|
||||
|
||||
Copyright (C) Jelmer Vernooij 2005-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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "lib/registry/registry.h"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/winreg.h"
|
||||
#include "system/filesys.h"
|
||||
|
||||
NTSTATUS torture_temp_dir(struct torture_context *tctx, const char *prefix,
|
||||
const char **tempdir);
|
||||
|
||||
static bool test_del_nonexistant_key(struct torture_context *tctx,
|
||||
const void *test_data)
|
||||
{
|
||||
const struct hive_key *root = test_data;
|
||||
WERROR error = hive_key_del(root, "bla");
|
||||
torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND,
|
||||
"invalid return code");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_keyinfo_root(struct torture_context *tctx,
|
||||
const void *test_data)
|
||||
{
|
||||
uint32_t num_subkeys, num_values;
|
||||
const struct hive_key *root = test_data;
|
||||
WERROR error;
|
||||
|
||||
/* This is a new backend. There should be no subkeys and no
|
||||
* values */
|
||||
error = hive_key_get_info(tctx, root, NULL, &num_subkeys, &num_values,
|
||||
NULL);
|
||||
torture_assert_werr_ok(tctx, error, "reg_key_num_subkeys()");
|
||||
|
||||
torture_assert_int_equal(tctx, num_subkeys, 0, "New key has non-zero subkey count");
|
||||
|
||||
torture_assert_werr_ok(tctx, error, "reg_key_num_values");
|
||||
|
||||
torture_assert_int_equal(tctx, num_values, 0, "New key has non-zero value count");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_keyinfo_nums(struct torture_context *tctx,
|
||||
const void *test_data)
|
||||
{
|
||||
uint32_t num_subkeys, num_values;
|
||||
const struct hive_key *root = test_data;
|
||||
WERROR error;
|
||||
struct hive_key *subkey;
|
||||
uint32_t data = 42;
|
||||
|
||||
error = hive_key_add_name(tctx, root, "Nested Keyll", NULL,
|
||||
NULL, &subkey);
|
||||
torture_assert_werr_ok(tctx, error, "hive_key_add_name");
|
||||
|
||||
error = hive_set_value(root, "Answer", REG_DWORD,
|
||||
data_blob_talloc(tctx, &data, sizeof(data)));
|
||||
torture_assert_werr_ok(tctx, error, "hive_set_value");
|
||||
|
||||
/* This is a new backend. There should be no subkeys and no
|
||||
* values */
|
||||
error = hive_key_get_info(tctx, root, NULL, &num_subkeys, &num_values,
|
||||
NULL);
|
||||
torture_assert_werr_ok(tctx, error, "reg_key_num_subkeys()");
|
||||
|
||||
torture_assert_int_equal(tctx, num_subkeys, 1, "subkey count");
|
||||
|
||||
torture_assert_werr_ok(tctx, error, "reg_key_num_values");
|
||||
|
||||
torture_assert_int_equal(tctx, num_values, 1, "value count");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_add_subkey(struct torture_context *tctx,
|
||||
const void *test_data)
|
||||
{
|
||||
WERROR error;
|
||||
struct hive_key *subkey;
|
||||
const struct hive_key *root = test_data;
|
||||
TALLOC_CTX *mem_ctx = tctx;
|
||||
|
||||
error = hive_key_add_name(mem_ctx, root, "Nested Key", NULL,
|
||||
NULL, &subkey);
|
||||
torture_assert_werr_ok(tctx, error, "hive_key_add_name");
|
||||
|
||||
error = hive_key_del(root, "Nested Key");
|
||||
torture_assert_werr_ok(tctx, error, "reg_key_del");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_flush_key(struct torture_context *tctx,
|
||||
const void *test_data)
|
||||
{
|
||||
const struct hive_key *root = test_data;
|
||||
|
||||
torture_assert_werr_ok(tctx, hive_key_flush(root), "flush key");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_del_key(struct torture_context *tctx, const void *test_data)
|
||||
{
|
||||
WERROR error;
|
||||
struct hive_key *subkey;
|
||||
const struct hive_key *root = test_data;
|
||||
TALLOC_CTX *mem_ctx = tctx;
|
||||
|
||||
error = hive_key_add_name(mem_ctx, root, "Nested Key", NULL,
|
||||
NULL, &subkey);
|
||||
torture_assert_werr_ok(tctx, error, "hive_key_add_name");
|
||||
|
||||
error = hive_key_del(root, "Nested Key");
|
||||
torture_assert_werr_ok(tctx, error, "reg_key_del");
|
||||
|
||||
error = hive_key_del(root, "Nested Key");
|
||||
torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND, "reg_key_del");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_set_value(struct torture_context *tctx,
|
||||
const void *test_data)
|
||||
{
|
||||
WERROR error;
|
||||
struct hive_key *subkey;
|
||||
const struct hive_key *root = test_data;
|
||||
TALLOC_CTX *mem_ctx = tctx;
|
||||
uint32_t data = 42;
|
||||
|
||||
error = hive_key_add_name(mem_ctx, root, "YA Nested Key", NULL,
|
||||
NULL, &subkey);
|
||||
torture_assert_werr_ok(tctx, error, "hive_key_add_name");
|
||||
|
||||
error = hive_set_value(subkey, "Answer", REG_DWORD,
|
||||
data_blob_talloc(mem_ctx, &data, sizeof(data)));
|
||||
torture_assert_werr_ok(tctx, error, "hive_set_value");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_get_value(struct torture_context *tctx, const void *test_data)
|
||||
{
|
||||
WERROR error;
|
||||
struct hive_key *subkey;
|
||||
const struct hive_key *root = test_data;
|
||||
TALLOC_CTX *mem_ctx = tctx;
|
||||
uint32_t data = 42;
|
||||
uint32_t type;
|
||||
DATA_BLOB value;
|
||||
|
||||
error = hive_key_add_name(mem_ctx, root, "EYA Nested Key", NULL,
|
||||
NULL, &subkey);
|
||||
torture_assert_werr_ok(tctx, error, "hive_key_add_name");
|
||||
|
||||
error = hive_get_value(mem_ctx, subkey, "Answer", &type, &value);
|
||||
torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND,
|
||||
"getting missing value");
|
||||
|
||||
error = hive_set_value(subkey, "Answer", REG_DWORD,
|
||||
data_blob_talloc(mem_ctx, &data, sizeof(data)));
|
||||
torture_assert_werr_ok(tctx, error, "hive_set_value");
|
||||
|
||||
error = hive_get_value(mem_ctx, subkey, "Answer", &type, &value);
|
||||
torture_assert_werr_ok(tctx, error, "getting value");
|
||||
|
||||
torture_assert(tctx, memcmp(value.data, &data, 4) == 0, "value data");
|
||||
|
||||
torture_assert_int_equal(tctx, value.length, 4, "value length");
|
||||
torture_assert_int_equal(tctx, type, REG_DWORD, "value type");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_del_value(struct torture_context *tctx, const void *test_data)
|
||||
{
|
||||
WERROR error;
|
||||
struct hive_key *subkey;
|
||||
const struct hive_key *root = test_data;
|
||||
TALLOC_CTX *mem_ctx = tctx;
|
||||
uint32_t data = 42;
|
||||
uint32_t type;
|
||||
DATA_BLOB value;
|
||||
|
||||
error = hive_key_add_name(mem_ctx, root, "EEYA Nested Key", NULL,
|
||||
NULL, &subkey);
|
||||
torture_assert_werr_ok(tctx, error, "hive_key_add_name");
|
||||
|
||||
error = hive_set_value(subkey, "Answer", REG_DWORD,
|
||||
data_blob_talloc(mem_ctx, &data, sizeof(data)));
|
||||
torture_assert_werr_ok(tctx, error, "hive_set_value");
|
||||
|
||||
error = hive_del_value(subkey, "Answer");
|
||||
torture_assert_werr_ok(tctx, error, "deleting value");
|
||||
|
||||
error = hive_get_value(mem_ctx, subkey, "Answer", &type, &value);
|
||||
torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND, "getting value");
|
||||
|
||||
error = hive_del_value(subkey, "Answer");
|
||||
torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND, "deleting value");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_list_values(struct torture_context *tctx,
|
||||
const void *test_data)
|
||||
{
|
||||
WERROR error;
|
||||
struct hive_key *subkey;
|
||||
const struct hive_key *root = test_data;
|
||||
TALLOC_CTX *mem_ctx = tctx;
|
||||
uint32_t data = 42;
|
||||
uint32_t type;
|
||||
DATA_BLOB value;
|
||||
const char *name;
|
||||
|
||||
error = hive_key_add_name(mem_ctx, root, "AYAYA Nested Key", NULL,
|
||||
NULL, &subkey);
|
||||
torture_assert_werr_ok(tctx, error, "hive_key_add_name");
|
||||
|
||||
error = hive_set_value(subkey, "Answer", REG_DWORD,
|
||||
data_blob_talloc(mem_ctx, &data, sizeof(data)));
|
||||
torture_assert_werr_ok(tctx, error, "hive_set_value");
|
||||
|
||||
error = hive_get_value_by_index(mem_ctx, subkey, 0, &name, &type, &value);
|
||||
torture_assert_werr_ok(tctx, error, "getting value");
|
||||
|
||||
torture_assert_str_equal(tctx, name, "Answer", "value name");
|
||||
torture_assert(tctx, memcmp(value.data, &data, 4) == 0, "value data");
|
||||
|
||||
torture_assert_int_equal(tctx, value.length, 4, "value length");
|
||||
torture_assert_int_equal(tctx, type, REG_DWORD, "value type");
|
||||
|
||||
error = hive_get_value_by_index(mem_ctx, subkey, 1, &name, &type, &value);
|
||||
torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS,
|
||||
"getting missing value");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void tcase_add_tests(struct torture_tcase *tcase)
|
||||
{
|
||||
torture_tcase_add_simple_test(tcase, "del_nonexistant_key",
|
||||
test_del_nonexistant_key);
|
||||
torture_tcase_add_simple_test(tcase, "add_subkey", test_add_subkey);
|
||||
torture_tcase_add_simple_test(tcase, "flush_key", test_flush_key);
|
||||
torture_tcase_add_simple_test(tcase, "get_info", test_keyinfo_root);
|
||||
torture_tcase_add_simple_test(tcase, "get_info_nums", test_keyinfo_nums);
|
||||
torture_tcase_add_simple_test(tcase, "set_value", test_set_value);
|
||||
torture_tcase_add_simple_test(tcase, "get_value", test_get_value);
|
||||
torture_tcase_add_simple_test(tcase, "list_values", test_list_values);
|
||||
torture_tcase_add_simple_test(tcase, "del_key", test_del_key);
|
||||
torture_tcase_add_simple_test(tcase, "del_value", test_del_value);
|
||||
}
|
||||
|
||||
static bool hive_setup_dir(struct torture_context *tctx, void **data)
|
||||
{
|
||||
struct hive_key *key;
|
||||
WERROR error;
|
||||
const char *dirname;
|
||||
NTSTATUS status;
|
||||
|
||||
status = torture_temp_dir(tctx, "hive-dir", &dirname);
|
||||
if (!NT_STATUS_IS_OK(status))
|
||||
return false;
|
||||
|
||||
rmdir(dirname);
|
||||
|
||||
error = reg_create_directory(tctx, dirname, &key);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Unable to initialize dir hive\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*data = key;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool hive_setup_ldb(struct torture_context *tctx, void **data)
|
||||
{
|
||||
struct hive_key *key;
|
||||
WERROR error;
|
||||
const char *dirname;
|
||||
NTSTATUS status;
|
||||
|
||||
status = torture_temp_dir(tctx, "hive-ldb", &dirname);
|
||||
if (!NT_STATUS_IS_OK(status))
|
||||
return false;
|
||||
|
||||
rmdir(dirname);
|
||||
|
||||
error = reg_open_ldb_file(tctx, dirname, NULL, NULL, &key);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Unable to initialize ldb hive\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*data = key;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool hive_setup_regf(struct torture_context *tctx, void **data)
|
||||
{
|
||||
struct hive_key *key;
|
||||
WERROR error;
|
||||
const char *dirname;
|
||||
NTSTATUS status;
|
||||
|
||||
status = torture_temp_dir(tctx, "hive-dir", &dirname);
|
||||
if (!NT_STATUS_IS_OK(status))
|
||||
return false;
|
||||
|
||||
rmdir(dirname);
|
||||
|
||||
error = reg_create_regf_file(tctx, dirname, 5, &key);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Unable to create new regf file\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*data = key;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_dir_refuses_null_location(struct torture_context *tctx)
|
||||
{
|
||||
torture_assert_werr_equal(tctx, WERR_INVALID_PARAM,
|
||||
reg_open_directory(NULL, NULL, NULL),
|
||||
"reg_open_directory accepts NULL location");
|
||||
return true;
|
||||
}
|
||||
|
||||
struct torture_suite *torture_registry_hive(TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct torture_tcase *tcase;
|
||||
struct torture_suite *suite = torture_suite_create(mem_ctx,
|
||||
"HIVE");
|
||||
|
||||
torture_suite_add_simple_test(suite, "dir-refuses-null-location",
|
||||
test_dir_refuses_null_location);
|
||||
|
||||
|
||||
tcase = torture_suite_add_tcase(suite, "dir");
|
||||
torture_tcase_set_fixture(tcase, hive_setup_dir, NULL);
|
||||
tcase_add_tests(tcase);
|
||||
|
||||
tcase = torture_suite_add_tcase(suite, "ldb");
|
||||
torture_tcase_set_fixture(tcase, hive_setup_ldb, NULL);
|
||||
tcase_add_tests(tcase);
|
||||
|
||||
tcase = torture_suite_add_tcase(suite, "regf");
|
||||
torture_tcase_set_fixture(tcase, hive_setup_regf, NULL);
|
||||
tcase_add_tests(tcase);
|
||||
|
||||
return suite;
|
||||
}
|
486
source4/lib/registry/tests/registry.c
Normal file
486
source4/lib/registry/tests/registry.c
Normal file
@ -0,0 +1,486 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
local testing of registry library - registry backend
|
||||
|
||||
Copyright (C) Jelmer Vernooij 2005-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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "lib/registry/registry.h"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/winreg.h"
|
||||
#include "system/filesys.h"
|
||||
|
||||
NTSTATUS torture_temp_dir(struct torture_context *tctx, const char *prefix,
|
||||
const char **tempdir);
|
||||
|
||||
/**
|
||||
* Test obtaining a predefined key.
|
||||
*/
|
||||
static bool test_get_predefined(struct torture_context *tctx,
|
||||
const void *_data)
|
||||
{
|
||||
const struct registry_context *rctx = _data;
|
||||
struct registry_key *root;
|
||||
WERROR error;
|
||||
|
||||
error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
|
||||
torture_assert_werr_ok(tctx, error,
|
||||
"getting predefined key failed");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating a new subkey
|
||||
*/
|
||||
static bool test_create_subkey(struct torture_context *tctx,
|
||||
const void *_data)
|
||||
{
|
||||
const struct registry_context *rctx = _data;
|
||||
struct registry_key *root, *newkey;
|
||||
WERROR error;
|
||||
|
||||
error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
|
||||
torture_assert_werr_ok(tctx, error,
|
||||
"getting predefined key failed");
|
||||
|
||||
error = reg_key_add_name(rctx, root, "Bad Bentheim", NULL, NULL, &newkey);
|
||||
torture_assert_werr_ok(tctx, error, "Creating key return code");
|
||||
torture_assert(tctx, newkey != NULL, "Creating new key");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating a new nested subkey
|
||||
*/
|
||||
static bool test_create_nested_subkey(struct torture_context *tctx,
|
||||
const void *_data)
|
||||
{
|
||||
const struct registry_context *rctx = _data;
|
||||
struct registry_key *root, *newkey1, *newkey2;
|
||||
WERROR error;
|
||||
|
||||
error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
|
||||
torture_assert_werr_ok(tctx, error,
|
||||
"getting predefined key failed");
|
||||
|
||||
error = reg_key_add_name(rctx, root, "Hamburg", NULL, NULL,
|
||||
&newkey1);
|
||||
torture_assert_werr_ok(tctx, error, "Creating key return code");
|
||||
torture_assert(tctx, newkey2 != NULL, "Creating new key");
|
||||
|
||||
error = reg_key_add_name(rctx, root, "Hamburg\\Hamburg", NULL, NULL,
|
||||
&newkey2);
|
||||
torture_assert_werr_ok(tctx, error, "Creating key return code");
|
||||
torture_assert(tctx, newkey2 != NULL, "Creating new key");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating a new subkey
|
||||
*/
|
||||
static bool test_key_add_abs_top(struct torture_context *tctx,
|
||||
const void *_data)
|
||||
{
|
||||
const struct registry_context *rctx = _data;
|
||||
struct registry_key *root;
|
||||
WERROR error;
|
||||
|
||||
error = reg_key_add_abs(tctx, rctx, "HKEY_CLASSES_ROOT", 0, NULL, &root);
|
||||
torture_assert_werr_equal(tctx, error, WERR_ALREADY_EXISTS, "create top level");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating a new subkey
|
||||
*/
|
||||
static bool test_key_add_abs(struct torture_context *tctx,
|
||||
const void *_data)
|
||||
{
|
||||
WERROR error;
|
||||
const struct registry_context *rctx = _data;
|
||||
struct registry_key *root, *result1, *result2;
|
||||
|
||||
error = reg_key_add_abs(tctx, rctx, "HKEY_CLASSES_ROOT\\bloe", 0, NULL, &result1);
|
||||
torture_assert_werr_ok(tctx, error, "create lowest");
|
||||
|
||||
error = reg_key_add_abs(tctx, rctx, "HKEY_CLASSES_ROOT\\bloe\\bla", 0, NULL, &result1);
|
||||
torture_assert_werr_ok(tctx, error, "create nested");
|
||||
|
||||
error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
|
||||
torture_assert_werr_ok(tctx, error,
|
||||
"getting predefined key failed");
|
||||
|
||||
error = reg_open_key(tctx, root, "bloe", &result2);
|
||||
torture_assert_werr_ok(tctx, error, "opening key");
|
||||
|
||||
error = reg_open_key(tctx, root, "bloe\\bla", &result2);
|
||||
torture_assert_werr_ok(tctx, error, "opening key");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool test_del_key(struct torture_context *tctx, const void *_data)
|
||||
{
|
||||
const struct registry_context *rctx = _data;
|
||||
struct registry_key *root, *newkey;
|
||||
WERROR error;
|
||||
|
||||
error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root);
|
||||
torture_assert_werr_ok(tctx, error,
|
||||
"getting predefined key failed");
|
||||
|
||||
error = reg_key_add_name(rctx, root, "Hamburg", NULL, NULL, &newkey);
|
||||
|
||||
torture_assert_werr_ok(tctx, error, "Creating key return code");
|
||||
torture_assert(tctx, newkey != NULL, "Creating new key");
|
||||
|
||||
error = reg_key_del(root, "Hamburg");
|
||||
torture_assert_werr_ok(tctx, error, "Delete key");
|
||||
|
||||
error = reg_key_del(root, "Hamburg");
|
||||
torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND,
|
||||
"Delete missing key");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function for opening the HKEY_CLASSES_ROOT hive and
|
||||
* creating a single key for testing purposes.
|
||||
*/
|
||||
static bool create_test_key(struct torture_context *tctx,
|
||||
const struct registry_context *rctx,
|
||||
const char *name,
|
||||
struct registry_key **root,
|
||||
struct registry_key **subkey)
|
||||
{
|
||||
WERROR error;
|
||||
|
||||
error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, root);
|
||||
torture_assert_werr_ok(tctx, error,
|
||||
"getting predefined key failed");
|
||||
|
||||
error = reg_key_add_name(rctx, *root, name, NULL, NULL, subkey);
|
||||
torture_assert_werr_ok(tctx, error, "Creating key return code");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool test_flush_key(struct torture_context *tctx, const void *_data)
|
||||
{
|
||||
const struct registry_context *rctx = _data;
|
||||
struct registry_key *root, *subkey;
|
||||
WERROR error;
|
||||
|
||||
if (!create_test_key(tctx, rctx, "Munchen", &root, &subkey))
|
||||
return false;
|
||||
|
||||
error = reg_key_flush(subkey);
|
||||
torture_assert_werr_ok(tctx, error, "flush key");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_query_key(struct torture_context *tctx, const void *_data)
|
||||
{
|
||||
const struct registry_context *rctx = _data;
|
||||
struct registry_key *root, *subkey;
|
||||
WERROR error;
|
||||
NTTIME last_changed_time;
|
||||
uint32_t num_subkeys, num_values;
|
||||
const char *classname;
|
||||
|
||||
if (!create_test_key(tctx, rctx, "Munchen", &root, &subkey))
|
||||
return false;
|
||||
|
||||
error = reg_key_get_info(tctx, subkey, &classname,
|
||||
&num_subkeys, &num_values,
|
||||
&last_changed_time);
|
||||
|
||||
torture_assert_werr_ok(tctx, error, "get info key");
|
||||
torture_assert(tctx, classname == NULL, "classname");
|
||||
torture_assert_int_equal(tctx, num_subkeys, 0, "num subkeys");
|
||||
torture_assert_int_equal(tctx, num_values, 0, "num values");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_query_key_nums(struct torture_context *tctx, const void *_data)
|
||||
{
|
||||
const struct registry_context *rctx = _data;
|
||||
struct registry_key *root, *subkey1, *subkey2;
|
||||
WERROR error;
|
||||
uint32_t num_subkeys, num_values;
|
||||
uint32_t data = 42;
|
||||
|
||||
if (!create_test_key(tctx, rctx, "Berlin", &root, &subkey1))
|
||||
return false;
|
||||
|
||||
error = reg_key_add_name(rctx, subkey1, "Bentheim", NULL, NULL, &subkey2);
|
||||
torture_assert_werr_ok(tctx, error, "Creating key return code");
|
||||
|
||||
error = reg_val_set(subkey1, "Answer", REG_DWORD,
|
||||
data_blob_talloc(tctx, &data, sizeof(data)));
|
||||
torture_assert_werr_ok(tctx, error, "set value");
|
||||
|
||||
error = reg_key_get_info(tctx, subkey1, NULL, &num_subkeys,
|
||||
&num_values, NULL);
|
||||
|
||||
torture_assert_werr_ok(tctx, error, "get info key");
|
||||
torture_assert_int_equal(tctx, num_subkeys, 1, "num subkeys");
|
||||
torture_assert_int_equal(tctx, num_values, 1, "num values");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the subkeys of a key can be enumerated, that
|
||||
* the returned parameters for get_subkey_by_index are optional and
|
||||
* that enumerating the parents of a non-top-level node works.
|
||||
*/
|
||||
static bool test_list_subkeys(struct torture_context *tctx, const void *_data)
|
||||
{
|
||||
const struct registry_context *rctx = _data;
|
||||
struct registry_key *subkey = NULL, *root;
|
||||
WERROR error;
|
||||
NTTIME last_mod_time;
|
||||
const char *classname, *name;
|
||||
|
||||
if (!create_test_key(tctx, rctx, "Goettingen", &root, &subkey))
|
||||
return false;
|
||||
|
||||
error = reg_key_get_subkey_by_index(tctx, root, 0, &name, &classname,
|
||||
&last_mod_time);
|
||||
|
||||
torture_assert_werr_ok(tctx, error, "Enum keys return code");
|
||||
torture_assert_str_equal(tctx, name, "Goettingen", "Enum keys data");
|
||||
|
||||
|
||||
error = reg_key_get_subkey_by_index(tctx, root, 0, NULL, NULL, NULL);
|
||||
|
||||
torture_assert_werr_ok(tctx, error, "Enum keys with NULL arguments return code");
|
||||
|
||||
error = reg_key_get_subkey_by_index(tctx, root, 1, NULL, NULL, NULL);
|
||||
|
||||
torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS,
|
||||
"Invalid error for no more items");
|
||||
|
||||
error = reg_key_get_subkey_by_index(tctx, subkey, 0, NULL, NULL, NULL);
|
||||
|
||||
torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS,
|
||||
"Invalid error for no more items");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setting a value
|
||||
*/
|
||||
static bool test_set_value(struct torture_context *tctx, const void *_data)
|
||||
{
|
||||
const struct registry_context *rctx = _data;
|
||||
struct registry_key *subkey = NULL, *root;
|
||||
WERROR error;
|
||||
uint32_t data = 42;
|
||||
|
||||
if (!create_test_key(tctx, rctx, "Dusseldorf", &root, &subkey))
|
||||
return false;
|
||||
|
||||
error = reg_val_set(subkey, "Answer", REG_DWORD,
|
||||
data_blob_talloc(tctx, &data, sizeof(data)));
|
||||
torture_assert_werr_ok (tctx, error, "setting value");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getting a value
|
||||
*/
|
||||
static bool test_get_value(struct torture_context *tctx, const void *_data)
|
||||
{
|
||||
const struct registry_context *rctx = _data;
|
||||
struct registry_key *subkey = NULL, *root;
|
||||
WERROR error;
|
||||
DATA_BLOB data;
|
||||
uint32_t value = 42;
|
||||
uint32_t type;
|
||||
|
||||
if (!create_test_key(tctx, rctx, "Duisburg", &root, &subkey))
|
||||
return false;
|
||||
|
||||
error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, &type,
|
||||
&data);
|
||||
torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND,
|
||||
"getting missing value");
|
||||
|
||||
error = reg_val_set(subkey, __FUNCTION__, REG_DWORD,
|
||||
data_blob_talloc(tctx, &value, 4));
|
||||
torture_assert_werr_ok (tctx, error, "setting value");
|
||||
|
||||
error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, &type,
|
||||
&data);
|
||||
torture_assert_werr_ok(tctx, error, "getting value");
|
||||
|
||||
torture_assert_int_equal(tctx, 4, data.length, "value length ok");
|
||||
torture_assert(tctx, memcmp(data.data, &value, 4) == 0, "value content ok");
|
||||
torture_assert_int_equal(tctx, REG_DWORD, type, "value type");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test unsetting a value
|
||||
*/
|
||||
static bool test_del_value(struct torture_context *tctx, const void *_data)
|
||||
{
|
||||
const struct registry_context *rctx = _data;
|
||||
struct registry_key *subkey = NULL, *root;
|
||||
WERROR error;
|
||||
DATA_BLOB data;
|
||||
uint32_t value = 42;
|
||||
uint32_t type;
|
||||
|
||||
if (!create_test_key(tctx, rctx, "Duisburg", &root, &subkey))
|
||||
return false;
|
||||
|
||||
error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, &type,
|
||||
&data);
|
||||
torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND,
|
||||
"getting missing value");
|
||||
|
||||
error = reg_val_set(subkey, __FUNCTION__, REG_DWORD,
|
||||
data_blob_talloc(tctx, &value, 4));
|
||||
torture_assert_werr_ok (tctx, error, "setting value");
|
||||
|
||||
error = reg_del_value(subkey, __FUNCTION__);
|
||||
torture_assert_werr_ok (tctx, error, "unsetting value");
|
||||
|
||||
error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, &type, &data);
|
||||
torture_assert_werr_equal(tctx, error, WERR_NOT_FOUND,
|
||||
"getting missing value");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test listing values
|
||||
*/
|
||||
static bool test_list_values(struct torture_context *tctx, const void *_data)
|
||||
{
|
||||
const struct registry_context *rctx = _data;
|
||||
struct registry_key *subkey = NULL, *root;
|
||||
WERROR error;
|
||||
DATA_BLOB data;
|
||||
uint32_t value = 42;
|
||||
uint32_t type;
|
||||
const char *name;
|
||||
|
||||
if (!create_test_key(tctx, rctx, "Bonn", &root, &subkey))
|
||||
return false;
|
||||
|
||||
error = reg_val_set(subkey, "bar", REG_DWORD,
|
||||
data_blob_talloc(tctx, &value, 4));
|
||||
torture_assert_werr_ok (tctx, error, "setting value");
|
||||
|
||||
error = reg_key_get_value_by_index(tctx, subkey, 0, &name, &type, &data);
|
||||
torture_assert_werr_ok(tctx, error, "getting value");
|
||||
|
||||
torture_assert_str_equal(tctx, name, "bar", "value name");
|
||||
torture_assert_int_equal(tctx, 4, data.length, "value length");
|
||||
torture_assert(tctx, memcmp(data.data, &value, 4) == 0, "value content");
|
||||
torture_assert_int_equal(tctx, REG_DWORD, type, "value type");
|
||||
|
||||
error = reg_key_get_value_by_index(tctx, subkey, 1, &name, &type, &data);
|
||||
torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS,
|
||||
"getting missing value");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool setup_local_registry(struct torture_context *tctx, void **data)
|
||||
{
|
||||
struct registry_context *rctx;
|
||||
WERROR error;
|
||||
const char *tempdir;
|
||||
NTSTATUS status;
|
||||
struct hive_key *hive_key;
|
||||
|
||||
error = reg_open_local(tctx, &rctx, NULL, NULL);
|
||||
if (!W_ERROR_IS_OK(error))
|
||||
return false;
|
||||
|
||||
status = torture_temp_dir(tctx, "registry-local", &tempdir);
|
||||
if (!NT_STATUS_IS_OK(status))
|
||||
return false;
|
||||
|
||||
error = reg_open_ldb_file(tctx,
|
||||
talloc_asprintf(tctx, "%s/classes_root.ldb", tempdir),
|
||||
NULL,
|
||||
NULL,
|
||||
&hive_key);
|
||||
if (!W_ERROR_IS_OK(error))
|
||||
return false;
|
||||
|
||||
error = reg_mount_hive(rctx, hive_key, HKEY_CLASSES_ROOT, NULL);
|
||||
if (!W_ERROR_IS_OK(error))
|
||||
return false;
|
||||
|
||||
*data = rctx;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void tcase_add_tests(struct torture_tcase *tcase)
|
||||
{
|
||||
torture_tcase_add_simple_test(tcase, "list_subkeys", test_list_subkeys);
|
||||
torture_tcase_add_simple_test(tcase, "get_predefined_key",
|
||||
test_get_predefined);
|
||||
torture_tcase_add_simple_test(tcase, "create_key", test_create_subkey);
|
||||
torture_tcase_add_simple_test(tcase, "create_key",
|
||||
test_create_nested_subkey);
|
||||
torture_tcase_add_simple_test(tcase, "key_add_abs", test_key_add_abs);
|
||||
torture_tcase_add_simple_test(tcase, "key_add_abs_top", test_key_add_abs_top);
|
||||
torture_tcase_add_simple_test(tcase, "set_value", test_set_value);
|
||||
torture_tcase_add_simple_test(tcase, "get_value", test_get_value);
|
||||
torture_tcase_add_simple_test(tcase, "list_values", test_list_values);
|
||||
torture_tcase_add_simple_test(tcase, "del_key", test_del_key);
|
||||
torture_tcase_add_simple_test(tcase, "del_value", test_del_value);
|
||||
torture_tcase_add_simple_test(tcase, "flush_key", test_flush_key);
|
||||
torture_tcase_add_simple_test(tcase, "query_key", test_query_key);
|
||||
torture_tcase_add_simple_test(tcase, "query_key_nums", test_query_key_nums);
|
||||
}
|
||||
|
||||
struct torture_suite *torture_registry_registry(TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct torture_tcase *tcase;
|
||||
struct torture_suite *suite = torture_suite_create(mem_ctx,
|
||||
"REGISTRY");
|
||||
|
||||
tcase = torture_suite_add_tcase(suite, "local");
|
||||
torture_tcase_set_fixture(tcase, setup_local_registry, NULL);
|
||||
tcase_add_tests(tcase);
|
||||
|
||||
return suite;
|
||||
}
|
75
source4/lib/registry/tools/common.c
Normal file
75
source4/lib/registry/tools/common.c
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Popt routines specifically for registry
|
||||
|
||||
Copyright (C) Jelmer Vernooij 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 "auth/credentials/credentials.h"
|
||||
#include "lib/registry/registry.h"
|
||||
|
||||
struct registry_context *reg_common_open_remote(const char *remote, struct cli_credentials *creds)
|
||||
{
|
||||
struct registry_context *h;
|
||||
WERROR error;
|
||||
|
||||
error = reg_open_remote(&h, NULL, creds, remote, NULL);
|
||||
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Unable to open remote registry at %s:%s \n", remote, win_errstr(error));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
struct registry_key *reg_common_open_file(const char *path, struct cli_credentials *creds)
|
||||
{
|
||||
struct hive_key *hive_root;
|
||||
struct registry_context *h;
|
||||
WERROR error;
|
||||
|
||||
error = reg_open_hive(NULL, path, NULL, creds, &hive_root);
|
||||
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Unable to open '%s': %s \n", path, win_errstr(error));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
error = reg_open_local(NULL, &h, NULL, creds);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Unable to initialize local registry: %s\n", win_errstr(error));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return reg_import_hive_key(h, hive_root, -1, NULL);
|
||||
}
|
||||
|
||||
struct registry_context *reg_common_open_local(struct cli_credentials *creds)
|
||||
{
|
||||
WERROR error;
|
||||
struct registry_context *h;
|
||||
|
||||
error = reg_open_samba(NULL, &h, NULL, creds);
|
||||
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Unable to open local registry:%s \n", win_errstr(error));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
@ -2,7 +2,8 @@
|
||||
Unix SMB/CIFS implementation.
|
||||
simple registry frontend
|
||||
|
||||
Copyright (C) Jelmer Vernooij 2004-2005
|
||||
Copyright (C) Jelmer Vernooij 2004-2007
|
||||
Copyright (C) Wilco Baan Hofman 2006
|
||||
|
||||
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
|
||||
@ -22,63 +23,115 @@
|
||||
#include "lib/registry/registry.h"
|
||||
#include "lib/events/events.h"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
#include "lib/registry/tools/common.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
enum reg_backend { REG_UNKNOWN, REG_LOCAL, REG_REMOTE, REG_NULL };
|
||||
|
||||
static struct registry_context *open_backend(poptContext pc, enum reg_backend backend, const char *remote_host)
|
||||
{
|
||||
WERROR error;
|
||||
struct registry_context *ctx;
|
||||
|
||||
switch (backend) {
|
||||
case REG_UNKNOWN:
|
||||
poptPrintUsage(pc, stderr, 0);
|
||||
return NULL;
|
||||
case REG_LOCAL:
|
||||
error = reg_open_samba(NULL, &ctx, NULL, cmdline_credentials);
|
||||
break;
|
||||
case REG_REMOTE:
|
||||
error = reg_open_remote(&ctx, NULL, cmdline_credentials, remote_host, NULL);
|
||||
break;
|
||||
case REG_NULL:
|
||||
error = reg_open_local(NULL, &ctx, NULL, cmdline_credentials);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Error: %s\n", win_errstr(error));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
int opt;
|
||||
poptContext pc;
|
||||
char *outputfile = NULL;
|
||||
enum reg_backend backend1 = REG_UNKNOWN, backend2 = REG_UNKNOWN;
|
||||
const char *remote1 = NULL, *remote2 = NULL;
|
||||
struct registry_context *h1 = NULL, *h2 = NULL;
|
||||
int from_null = 0;
|
||||
WERROR error;
|
||||
struct reg_diff *diff;
|
||||
struct poptOption long_options[] = {
|
||||
POPT_AUTOHELP
|
||||
{"output", 'o', POPT_ARG_STRING, &outputfile, 'o', "output file to use", NULL },
|
||||
{"null", 'n', POPT_ARG_NONE, &from_null, 'n', "Diff from NULL", NULL },
|
||||
{"remote", 'R', POPT_ARG_STRING, NULL, 0, "Connect to remote server" , NULL },
|
||||
{"local", 'L', POPT_ARG_NONE, NULL, 0, "Open local registry", NULL },
|
||||
{"output", 'o', POPT_ARG_STRING, &outputfile, 0, "output file to use", NULL },
|
||||
{"null", 'n', POPT_ARG_NONE, NULL, 'n', "Diff from NULL", NULL },
|
||||
{"remote", 'R', POPT_ARG_STRING, NULL, 'R', "Connect to remote server" , NULL },
|
||||
{"local", 'L', POPT_ARG_NONE, NULL, 'L', "Open local registry", NULL },
|
||||
POPT_COMMON_SAMBA
|
||||
POPT_COMMON_CREDENTIALS
|
||||
POPT_COMMON_VERSION
|
||||
{ NULL }
|
||||
};
|
||||
TALLOC_CTX *ctx;
|
||||
void *callback_data;
|
||||
struct reg_diff_callbacks *callbacks;
|
||||
|
||||
registry_init();
|
||||
ctx = talloc_init("regdiff");
|
||||
|
||||
pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0);
|
||||
pc = poptGetContext(argv[0], argc, argv, long_options,0);
|
||||
|
||||
while((opt = poptGetNextOpt(pc)) != -1) {
|
||||
error = WERR_OK;
|
||||
switch(opt) {
|
||||
case 'L':
|
||||
if (!h1 && !from_null) error = reg_open_local(NULL, &h1, NULL, cmdline_credentials);
|
||||
else if (!h2) error = reg_open_local(NULL, &h2, NULL, cmdline_credentials);
|
||||
if (backend1 == REG_UNKNOWN)
|
||||
backend1 = REG_LOCAL;
|
||||
else if (backend2 == REG_UNKNOWN)
|
||||
backend2 = REG_LOCAL;
|
||||
break;
|
||||
case 'n':
|
||||
if (backend1 == REG_UNKNOWN)
|
||||
backend1 = REG_NULL;
|
||||
else if (backend2 == REG_UNKNOWN)
|
||||
backend2 = REG_NULL;
|
||||
break;
|
||||
case 'R':
|
||||
if (!h1 && !from_null)
|
||||
error = reg_open_remote(&h1, NULL, cmdline_credentials,
|
||||
poptGetOptArg(pc), NULL);
|
||||
else if (!h2) error = reg_open_remote(&h2, NULL, cmdline_credentials,
|
||||
poptGetOptArg(pc), NULL);
|
||||
if (backend1 == REG_UNKNOWN) {
|
||||
backend1 = REG_REMOTE;
|
||||
remote1 = poptGetOptArg(pc);
|
||||
} else if (backend2 == REG_UNKNOWN) {
|
||||
backend2 = REG_REMOTE;
|
||||
remote2 = poptGetOptArg(pc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Error: %s\n", win_errstr(error));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
h1 = open_backend(pc, backend1, remote1);
|
||||
if (h1 == NULL)
|
||||
return 1;
|
||||
|
||||
h2 = open_backend(pc, backend2, remote2);
|
||||
if (h2 == NULL)
|
||||
return 1;
|
||||
|
||||
poptFreeContext(pc);
|
||||
|
||||
diff = reg_generate_diff(NULL, h1, h2);
|
||||
if (!diff) {
|
||||
fprintf(stderr, "Unable to generate diff between keys\n");
|
||||
error = reg_dotreg_diff_save(ctx, outputfile, &callbacks, &callback_data);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Problem saving registry diff to '%s': %s\n", outputfile, win_errstr(error));
|
||||
return -1;
|
||||
}
|
||||
|
||||
reg_diff_save(diff, outputfile);
|
||||
error = reg_generate_diff(h1, h2, callbacks, callback_data);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Unable to generate diff between keys: %s\n", win_errstr(error));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
Unix SMB/CIFS implementation.
|
||||
simple registry frontend
|
||||
|
||||
Copyright (C) 2004-2005 Jelmer Vernooij, jelmer@samba.org
|
||||
Copyright (C) 2004-2007 Jelmer Vernooij, jelmer@samba.org
|
||||
|
||||
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
|
||||
@ -22,6 +22,8 @@
|
||||
#include "lib/events/events.h"
|
||||
#include "lib/registry/registry.h"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
#include "lib/registry/tools/common.h"
|
||||
#include "lib/registry/patchfile.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@ -29,12 +31,12 @@ int main(int argc, char **argv)
|
||||
poptContext pc;
|
||||
const char *patch;
|
||||
struct registry_context *h;
|
||||
const char *file = NULL;
|
||||
const char *remote = NULL;
|
||||
struct reg_diff *diff;
|
||||
WERROR error;
|
||||
struct poptOption long_options[] = {
|
||||
POPT_AUTOHELP
|
||||
{"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL},
|
||||
{"file", 'F', POPT_ARG_STRING, &file, 0, "file path", NULL },
|
||||
POPT_COMMON_SAMBA
|
||||
POPT_COMMON_CREDENTIALS
|
||||
{ NULL }
|
||||
@ -45,29 +47,24 @@ int main(int argc, char **argv)
|
||||
while((opt = poptGetNextOpt(pc)) != -1) {
|
||||
}
|
||||
|
||||
registry_init();
|
||||
|
||||
if (remote) {
|
||||
error = reg_open_remote (&h, NULL, cmdline_credentials, remote, NULL);
|
||||
h = reg_common_open_remote (remote, cmdline_credentials);
|
||||
} else {
|
||||
error = reg_open_local (NULL, &h, NULL, cmdline_credentials);
|
||||
h = reg_common_open_local (cmdline_credentials);
|
||||
}
|
||||
|
||||
if (W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Error: %s\n", win_errstr(error));
|
||||
|
||||
if (h == NULL)
|
||||
return 1;
|
||||
}
|
||||
|
||||
patch = poptGetArg(pc);
|
||||
poptFreeContext(pc);
|
||||
|
||||
diff = reg_diff_load(NULL, patch);
|
||||
if (!diff) {
|
||||
fprintf(stderr, "Unable to load registry patch from `%s'\n", patch);
|
||||
if (patch == NULL) {
|
||||
poptPrintUsage(pc, stderr, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
reg_diff_apply(diff, h);
|
||||
poptFreeContext(pc);
|
||||
|
||||
reg_diff_apply(patch, h);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
Unix SMB/CIFS implementation.
|
||||
simple registry frontend
|
||||
|
||||
Copyright (C) Jelmer Vernooij 2004
|
||||
Copyright (C) Jelmer Vernooij 2004-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
|
||||
@ -25,8 +25,15 @@
|
||||
#include "system/time.h"
|
||||
#include "lib/smbreadline/smbreadline.h"
|
||||
#include "librpc/gen_ndr/ndr_security.h"
|
||||
#include "lib/registry/tools/common.h"
|
||||
|
||||
/*
|
||||
struct regshell_context {
|
||||
struct registry_context *registry;
|
||||
const char *path;
|
||||
struct registry_key *current;
|
||||
};
|
||||
|
||||
/* *
|
||||
* ck/cd - change key
|
||||
* ls - list values/keys
|
||||
* rmval/rm - remove value
|
||||
@ -40,29 +47,40 @@
|
||||
* exit
|
||||
*/
|
||||
|
||||
static struct registry_key *cmd_info(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
|
||||
static WERROR cmd_info(struct regshell_context *ctx, int argc, char **argv)
|
||||
{
|
||||
struct security_descriptor *sec_desc = NULL;
|
||||
time_t last_mod;
|
||||
WERROR error;
|
||||
const char *classname;
|
||||
NTTIME last_change;
|
||||
|
||||
error = reg_key_get_info(ctx, ctx->current, &classname, NULL, NULL, &last_change);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
printf("Error getting key info: %s\n", win_errstr(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
printf("Name: %s\n", cur->name);
|
||||
printf("Full path: %s\n", cur->path);
|
||||
printf("Key Class: %s\n", cur->class_name);
|
||||
last_mod = nt_time_to_unix(cur->last_mod);
|
||||
printf("Name: %s\n", strchr(ctx->path, '\\')?strrchr(ctx->path, '\\')+1:
|
||||
ctx->path);
|
||||
printf("Full path: %s\n", ctx->path);
|
||||
printf("Key Class: %s\n", classname);
|
||||
last_mod = nt_time_to_unix(last_change);
|
||||
printf("Time Last Modified: %s\n", ctime(&last_mod));
|
||||
|
||||
error = reg_get_sec_desc(mem_ctx, cur, &sec_desc);
|
||||
error = reg_get_sec_desc(ctx, ctx->current, &sec_desc);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
printf("Error getting security descriptor\n");
|
||||
} else {
|
||||
ndr_print_debug((ndr_print_fn_t)ndr_print_security_descriptor, "Security", sec_desc);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
ndr_print_debug((ndr_print_fn_t)ndr_print_security_descriptor, "Security", sec_desc);
|
||||
talloc_free(sec_desc);
|
||||
return cur;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct registry_key *cmd_predef(TALLOC_CTX *mem_ctx, struct registry_context *ctx, struct registry_key *cur, int argc, char **argv)
|
||||
static WERROR cmd_predef(struct regshell_context *ctx, int argc, char **argv)
|
||||
{
|
||||
struct registry_key *ret = NULL;
|
||||
if (argc < 2) {
|
||||
@ -70,165 +88,195 @@ static struct registry_key *cmd_predef(TALLOC_CTX *mem_ctx, struct registry_cont
|
||||
} else if (!ctx) {
|
||||
fprintf(stderr, "No full registry loaded, no predefined keys defined\n");
|
||||
} else {
|
||||
WERROR error = reg_get_predefined_key_by_name(ctx, argv[1], &ret);
|
||||
WERROR error = reg_get_predefined_key_by_name(ctx->registry, argv[1], &ret);
|
||||
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Error opening predefined key %s: %s\n", argv[1], win_errstr(error));
|
||||
ret = NULL;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct registry_key *cmd_pwd(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
|
||||
static WERROR cmd_pwd(struct regshell_context *ctx,
|
||||
int argc, char **argv)
|
||||
{
|
||||
printf("%s\n", cur->path);
|
||||
return cur;
|
||||
printf("%s\n", ctx->path);
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct registry_key *cmd_set(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
|
||||
static WERROR cmd_set(struct regshell_context *ctx, int argc, char **argv)
|
||||
{
|
||||
struct registry_value val;
|
||||
WERROR error;
|
||||
|
||||
if (argc < 4) {
|
||||
fprintf(stderr, "Usage: set value-name type value\n");
|
||||
return cur;
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (!reg_string_to_val(mem_ctx, argv[2], argv[3], &val.data_type, &val.data)) {
|
||||
if (!reg_string_to_val(ctx, argv[2], argv[3], &val.data_type,
|
||||
&val.data)) {
|
||||
fprintf(stderr, "Unable to interpret data\n");
|
||||
return cur;
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
error = reg_val_set(cur, argv[1], val.data_type, val.data);
|
||||
error = reg_val_set(ctx->current, argv[1], val.data_type, val.data);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Error setting value: %s\n", win_errstr(error));
|
||||
return NULL;
|
||||
return error;
|
||||
}
|
||||
return cur;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct registry_key *cmd_ck(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
|
||||
static WERROR cmd_ck(struct regshell_context *ctx, int argc, char **argv)
|
||||
{
|
||||
struct registry_key *new = NULL;
|
||||
WERROR error;
|
||||
|
||||
if(argc < 2) {
|
||||
new = cur;
|
||||
new = ctx->current;
|
||||
} else {
|
||||
error = reg_open_key(mem_ctx, cur, argv[1], &new);
|
||||
error = reg_open_key(ctx->registry, ctx->current, argv[1], &new);
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(0, ("Error opening specified key: %s\n", win_errstr(error)));
|
||||
return NULL;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Current path is: %s\n", new->path);
|
||||
ctx->path = talloc_asprintf(ctx, "%s\\%s", ctx->path, argv[1]);
|
||||
printf("Current path is: %s\n", ctx->path);
|
||||
ctx->current = new;
|
||||
|
||||
return new;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct registry_key *cmd_print(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
|
||||
static WERROR cmd_print(struct regshell_context *ctx, int argc, char **argv)
|
||||
{
|
||||
struct registry_value *value;
|
||||
uint32_t value_type;
|
||||
DATA_BLOB value_data;
|
||||
WERROR error;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: print <valuename>");
|
||||
return NULL;
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
error = reg_key_get_value_by_name(mem_ctx, cur, argv[1], &value);
|
||||
error = reg_key_get_value_by_name(ctx, ctx->current, argv[1],
|
||||
&value_type, &value_data);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "No such value '%s'\n", argv[1]);
|
||||
return NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
printf("%s\n%s\n", str_regtype(value->data_type), reg_val_data_string(mem_ctx, value->data_type, &value->data));
|
||||
return NULL;
|
||||
printf("%s\n%s\n", str_regtype(value_type),
|
||||
reg_val_data_string(ctx, value_type, value_data));
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct registry_key *cmd_ls(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
|
||||
static WERROR cmd_ls(struct regshell_context *ctx, int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
WERROR error;
|
||||
struct registry_value *value;
|
||||
struct registry_key *sub;
|
||||
for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, cur, i, &sub)); i++) {
|
||||
printf("K %s\n", sub->name);
|
||||
uint32_t data_type;
|
||||
DATA_BLOB data;
|
||||
const char *name;
|
||||
|
||||
for (i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(ctx, ctx->current, i, &name, NULL, NULL)); i++) {
|
||||
printf("K %s\n", name);
|
||||
}
|
||||
|
||||
if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
|
||||
if (!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
|
||||
DEBUG(0, ("Error occured while browsing thru keys: %s\n", win_errstr(error)));
|
||||
}
|
||||
|
||||
for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(mem_ctx, cur, i, &value)); i++) {
|
||||
printf("V \"%s\" %s %s\n", value->name, str_regtype(value->data_type), reg_val_data_string(mem_ctx, value->data_type, &value->data));
|
||||
for (i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(ctx, ctx->current, i, &name, &data_type, &data)); i++) {
|
||||
printf("V \"%s\" %s %s\n", value->name, str_regtype(data_type),
|
||||
reg_val_data_string(ctx, data_type, data));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return WERR_OK;
|
||||
}
|
||||
static struct registry_key *cmd_mkkey(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
|
||||
static WERROR cmd_mkkey(struct regshell_context *ctx, int argc, char **argv)
|
||||
{
|
||||
struct registry_key *tmp;
|
||||
WERROR error;
|
||||
|
||||
if(argc < 2) {
|
||||
fprintf(stderr, "Usage: mkkey <keyname>\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(reg_key_add_name(mem_ctx, cur, argv[1], 0, NULL, &tmp))) {
|
||||
fprintf(stderr, "Error adding new subkey '%s'\n", argv[1]);
|
||||
return NULL;
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
error = reg_key_add_name(ctx, ctx->current, argv[1], 0, NULL, &tmp);
|
||||
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Error adding new subkey '%s'\n", argv[1]);
|
||||
return error;
|
||||
}
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct registry_key *cmd_rmkey(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
|
||||
static WERROR cmd_rmkey(struct regshell_context *ctx,
|
||||
int argc, char **argv)
|
||||
{
|
||||
WERROR error;
|
||||
|
||||
if(argc < 2) {
|
||||
fprintf(stderr, "Usage: rmkey <name>\n");
|
||||
return NULL;
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(reg_key_del(cur, argv[1]))) {
|
||||
error = reg_key_del(ctx->current, argv[1]);
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Error deleting '%s'\n", argv[1]);
|
||||
return error;
|
||||
} else {
|
||||
fprintf(stderr, "Successfully deleted '%s'\n", argv[1]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
|
||||
static WERROR cmd_rmval(struct regshell_context *ctx, int argc, char **argv)
|
||||
{
|
||||
WERROR error;
|
||||
|
||||
if(argc < 2) {
|
||||
fprintf(stderr, "Usage: rmval <valuename>\n");
|
||||
return NULL;
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(reg_del_value(cur, argv[1]))) {
|
||||
error = reg_del_value(ctx->current, argv[1]);
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Error deleting value '%s'\n", argv[1]);
|
||||
return error;
|
||||
} else {
|
||||
fprintf(stderr, "Successfully deleted value '%s'\n", argv[1]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct registry_key *cmd_exit(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
|
||||
static WERROR cmd_exit(struct regshell_context *ctx,
|
||||
int argc, char **argv)
|
||||
{
|
||||
exit(0);
|
||||
return NULL;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *, int, char **);
|
||||
static WERROR cmd_help(struct regshell_context *ctx, int, char **);
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
const char *alias;
|
||||
const char *help;
|
||||
struct registry_key *(*handle)(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *, int argc, char **argv);
|
||||
WERROR (*handle)(struct regshell_context *ctx,
|
||||
int argc, char **argv);
|
||||
} regshell_cmds[] = {
|
||||
{"ck", "cd", "Change current key", cmd_ck },
|
||||
{"info", "i", "Show detailed information of a key", cmd_info },
|
||||
@ -245,17 +293,19 @@ static struct {
|
||||
{NULL }
|
||||
};
|
||||
|
||||
static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_context *ctx, struct registry_key *cur, int argc, char **argv)
|
||||
static WERROR cmd_help(struct regshell_context *ctx,
|
||||
int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
printf("Available commands:\n");
|
||||
for(i = 0; regshell_cmds[i].name; i++) {
|
||||
printf("%s - %s\n", regshell_cmds[i].name, regshell_cmds[i].help);
|
||||
}
|
||||
return NULL;
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static struct registry_key *process_cmd(TALLOC_CTX *mem_ctx, struct registry_context *ctx, struct registry_key *k, char *line)
|
||||
static WERROR process_cmd(struct regshell_context *ctx,
|
||||
char *line)
|
||||
{
|
||||
int argc;
|
||||
char **argv = NULL;
|
||||
@ -263,19 +313,19 @@ static struct registry_key *process_cmd(TALLOC_CTX *mem_ctx, struct registry_con
|
||||
|
||||
if ((ret = poptParseArgvString(line, &argc, (const char ***) &argv)) != 0) {
|
||||
fprintf(stderr, "regshell: %s\n", poptStrerror(ret));
|
||||
return k;
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
for(i = 0; regshell_cmds[i].name; i++) {
|
||||
if(!strcmp(regshell_cmds[i].name, argv[0]) ||
|
||||
(regshell_cmds[i].alias && !strcmp(regshell_cmds[i].alias, argv[0]))) {
|
||||
return regshell_cmds[i].handle(mem_ctx, ctx, k, argc, argv);
|
||||
return regshell_cmds[i].handle(ctx, argc, argv);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "No such command '%s'\n", argv[0]);
|
||||
|
||||
return k;
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
#define MAX_COMPLETIONS 100
|
||||
@ -333,7 +383,7 @@ cleanup:
|
||||
static char **reg_complete_key(const char *text, int start, int end)
|
||||
{
|
||||
struct registry_key *base;
|
||||
struct registry_key *subkey;
|
||||
const char *subkeyname;
|
||||
int i, j = 1;
|
||||
int samelen = 0;
|
||||
int len;
|
||||
@ -351,10 +401,11 @@ static char **reg_complete_key(const char *text, int start, int end)
|
||||
|
||||
len = strlen(text);
|
||||
for(i = 0; j < MAX_COMPLETIONS-1; i++) {
|
||||
status = reg_key_get_subkey_by_index(mem_ctx, base, i, &subkey);
|
||||
status = reg_key_get_subkey_by_index(mem_ctx, base, i, &subkeyname,
|
||||
NULL, NULL);
|
||||
if(W_ERROR_IS_OK(status)) {
|
||||
if(!strncmp(text, subkey->name, len)) {
|
||||
matches[j] = strdup(subkey->name);
|
||||
if(!strncmp(text, subkeyname, len)) {
|
||||
matches[j] = strdup(subkeyname);
|
||||
j++;
|
||||
|
||||
if (j == 1)
|
||||
@ -381,7 +432,8 @@ static char **reg_complete_key(const char *text, int start, int end)
|
||||
if (j == 2) { /* Exact match */
|
||||
asprintf(&matches[0], "%s%s", base_n, matches[1]);
|
||||
} else {
|
||||
asprintf(&matches[0], "%s%s", base_n, talloc_strndup(mem_ctx, matches[1], samelen));
|
||||
asprintf(&matches[0], "%s%s", base_n,
|
||||
talloc_strndup(mem_ctx, matches[1], samelen));
|
||||
}
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
@ -400,19 +452,17 @@ static char **reg_completion(const char *text, int start, int end)
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int opt;
|
||||
const char *backend = NULL;
|
||||
struct registry_key *curkey = NULL;
|
||||
const char *file = NULL;
|
||||
poptContext pc;
|
||||
WERROR error;
|
||||
TALLOC_CTX *mem_ctx = talloc_init("cmd");
|
||||
const char *remote = NULL;
|
||||
struct registry_context *h = NULL;
|
||||
struct regshell_context *ctx;
|
||||
bool ret = true;
|
||||
struct poptOption long_options[] = {
|
||||
POPT_AUTOHELP
|
||||
{"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL},
|
||||
{"file", 'F', POPT_ARG_STRING, &file, 0, "open hive file", NULL },
|
||||
{"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL},
|
||||
POPT_COMMON_SAMBA
|
||||
POPT_COMMON_CREDENTIALS
|
||||
@ -425,64 +475,62 @@ static char **reg_completion(const char *text, int start, int end)
|
||||
while((opt = poptGetNextOpt(pc)) != -1) {
|
||||
}
|
||||
|
||||
registry_init();
|
||||
ctx = talloc_zero(NULL, struct regshell_context);
|
||||
|
||||
if (remote) {
|
||||
error = reg_open_remote (&h, NULL, cmdline_credentials, remote, NULL);
|
||||
} else if (backend) {
|
||||
error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, cmdline_credentials, &curkey);
|
||||
if (remote != NULL) {
|
||||
ctx->registry = reg_common_open_remote(remote, cmdline_credentials);
|
||||
} else if (file != NULL) {
|
||||
ctx->current = reg_common_open_file(file, cmdline_credentials);
|
||||
ctx->registry = ctx->current->context;
|
||||
ctx->path = talloc_strdup(ctx, "");
|
||||
} else {
|
||||
error = reg_open_local(NULL, &h, NULL, cmdline_credentials);
|
||||
ctx->registry = reg_common_open_local(cmdline_credentials);
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Unable to open registry\n");
|
||||
if (ctx->registry == NULL)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (h) {
|
||||
if (ctx->current == NULL) {
|
||||
int i;
|
||||
|
||||
for (i = 0; reg_predefined_keys[i].handle; i++) {
|
||||
WERROR err;
|
||||
err = reg_get_predefined_key(h, reg_predefined_keys[i].handle, &curkey);
|
||||
err = reg_get_predefined_key(ctx->registry,
|
||||
reg_predefined_keys[i].handle,
|
||||
&ctx->current);
|
||||
if (W_ERROR_IS_OK(err)) {
|
||||
ctx->path = talloc_strdup(ctx, reg_predefined_keys[i].name);
|
||||
break;
|
||||
} else {
|
||||
curkey = NULL;
|
||||
ctx->current = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!curkey) {
|
||||
if (ctx->current == NULL) {
|
||||
fprintf(stderr, "Unable to access any of the predefined keys\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
poptFreeContext(pc);
|
||||
|
||||
while(True) {
|
||||
while (true) {
|
||||
char *line, *prompt;
|
||||
|
||||
if(curkey->hive->root->name) {
|
||||
asprintf(&prompt, "%s:%s> ", curkey->hive->root->name, curkey->path);
|
||||
} else {
|
||||
asprintf(&prompt, "%s> ", curkey->path);
|
||||
}
|
||||
asprintf(&prompt, "%s> ", ctx->path);
|
||||
|
||||
current_key = curkey; /* No way to pass a void * pointer
|
||||
via readline :-( */
|
||||
current_key = ctx->current; /* No way to pass a void * pointer
|
||||
via readline :-( */
|
||||
line = smb_readline(prompt, NULL, reg_completion);
|
||||
|
||||
if(!line)
|
||||
if (line == NULL)
|
||||
break;
|
||||
|
||||
if(line[0] != '\n') {
|
||||
struct registry_key *new = process_cmd(mem_ctx, h, curkey, line);
|
||||
if(new)curkey = new;
|
||||
if (line[0] != '\n') {
|
||||
ret = W_ERROR_IS_OK(process_cmd(ctx, line));
|
||||
}
|
||||
}
|
||||
talloc_free(mem_ctx);
|
||||
talloc_free(ctx);
|
||||
|
||||
return 0;
|
||||
return (ret?0:1);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
Unix SMB/CIFS implementation.
|
||||
simple registry frontend
|
||||
|
||||
Copyright (C) Jelmer Vernooij 2004
|
||||
Copyright (C) Jelmer Vernooij 2004-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
|
||||
@ -20,52 +20,66 @@
|
||||
|
||||
#include "includes.h"
|
||||
#include "lib/registry/registry.h"
|
||||
#include "lib/registry/tools/common.h"
|
||||
#include "lib/events/events.h"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
|
||||
static void print_tree(int l, struct registry_key *p, int fullpath, int novals)
|
||||
/**
|
||||
* Print a registry key recursively
|
||||
*
|
||||
* @param level Level at which to print
|
||||
* @param p Key to print
|
||||
* @param fullpath Whether the full pat hshould be printed or just the last bit
|
||||
* @param novals Whether values should not be printed
|
||||
*/
|
||||
static void print_tree(int level, struct registry_key *p,
|
||||
const char *name,
|
||||
bool fullpath, bool novals)
|
||||
{
|
||||
struct registry_key *subkey;
|
||||
struct registry_value *value;
|
||||
const char *valuename;
|
||||
const char *keyname;
|
||||
uint32_t value_type;
|
||||
DATA_BLOB value_data;
|
||||
struct security_descriptor *sec_desc;
|
||||
WERROR error;
|
||||
int i;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
|
||||
for(i = 0; i < l; i++) putchar(' ');
|
||||
|
||||
/* Hive name */
|
||||
if(p->hive->root == p) {
|
||||
if(p->hive->root->name) printf("%s\n", p->hive->root->name); else printf("<No Name>\n");
|
||||
} else {
|
||||
if(!p->name) printf("<No Name>\n");
|
||||
if(fullpath) printf("%s\n", p->path);
|
||||
else printf("%s\n", p->name?p->name:"(NULL)");
|
||||
}
|
||||
for(i = 0; i < level; i++) putchar(' '); puts(name);
|
||||
|
||||
mem_ctx = talloc_init("print_tree");
|
||||
for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, p, i, &subkey)); i++) {
|
||||
print_tree(l+1, subkey, fullpath, novals);
|
||||
for (i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, p, i, &keyname, NULL, NULL)); i++) {
|
||||
SMB_ASSERT(strlen(keyname) > 0);
|
||||
if (!W_ERROR_IS_OK(reg_open_key(mem_ctx, p, keyname, &subkey)))
|
||||
continue;
|
||||
print_tree(level+1, subkey, (fullpath && strlen(name))?
|
||||
talloc_asprintf(mem_ctx, "%s\\%s", name, keyname):
|
||||
keyname, fullpath, novals);
|
||||
}
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
|
||||
DEBUG(0, ("Error occured while fetching subkeys for '%s': %s\n", p->path, win_errstr(error)));
|
||||
DEBUG(0, ("Error occured while fetching subkeys for '%s': %s\n",
|
||||
name, win_errstr(error)));
|
||||
}
|
||||
|
||||
if(!novals) {
|
||||
if (!novals) {
|
||||
mem_ctx = talloc_init("print_tree");
|
||||
for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(mem_ctx, p, i, &value)); i++) {
|
||||
for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(mem_ctx,
|
||||
p, i, &valuename, &value_type, &value_data)); i++) {
|
||||
int j;
|
||||
char *desc;
|
||||
for(j = 0; j < l+1; j++) putchar(' ');
|
||||
desc = reg_val_description(mem_ctx, value);
|
||||
for(j = 0; j < level+1; j++) putchar(' ');
|
||||
desc = reg_val_description(mem_ctx, valuename, value_type,
|
||||
value_data);
|
||||
printf("%s\n", desc);
|
||||
}
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
|
||||
DEBUG(0, ("Error occured while fetching values for '%s': %s\n", p->path, win_errstr(error)));
|
||||
DEBUG(0, ("Error occured while fetching values for '%s': %s\n",
|
||||
name, win_errstr(error)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,21 +93,22 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int opt, i;
|
||||
const char *backend = NULL;
|
||||
const char *file = NULL;
|
||||
const char *remote = NULL;
|
||||
poptContext pc;
|
||||
struct registry_context *h = NULL;
|
||||
struct registry_key *root = NULL;
|
||||
struct registry_key *start_key = NULL;
|
||||
WERROR error;
|
||||
int fullpath = 0, no_values = 0;
|
||||
bool fullpath = false, no_values = false;
|
||||
struct poptOption long_options[] = {
|
||||
POPT_AUTOHELP
|
||||
{"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL},
|
||||
{"fullpath", 'f', POPT_ARG_NONE, &fullpath, 0, "show full paths", NULL},
|
||||
{"file", 'F', POPT_ARG_STRING, &file, 0, "file path", NULL },
|
||||
{"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL },
|
||||
{"fullpath", 'f', POPT_ARG_NONE, &fullpath, 0, "show full paths", NULL},
|
||||
{"no-values", 'V', POPT_ARG_NONE, &no_values, 0, "don't show values", NULL},
|
||||
POPT_COMMON_SAMBA
|
||||
POPT_COMMON_CREDENTIALS
|
||||
POPT_COMMON_VERSION
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@ -102,48 +117,35 @@ int main(int argc, char **argv)
|
||||
while((opt = poptGetNextOpt(pc)) != -1) {
|
||||
}
|
||||
|
||||
registry_init();
|
||||
|
||||
if (remote) {
|
||||
error = reg_open_remote(&h, NULL, cmdline_credentials, remote, NULL);
|
||||
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Unable to open remote registry at %s:%s \n", remote, win_errstr(error));
|
||||
return 1;
|
||||
}
|
||||
|
||||
} else if (backend) {
|
||||
error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, cmdline_credentials, &root);
|
||||
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Unable to open '%s' with backend '%s':%s \n", poptGetArg(pc), backend, win_errstr(error));
|
||||
return 1;
|
||||
}
|
||||
if (remote != NULL) {
|
||||
h = reg_common_open_remote(remote, cmdline_credentials);
|
||||
} else if (file != NULL) {
|
||||
start_key = reg_common_open_file(file, cmdline_credentials);
|
||||
} else {
|
||||
error = reg_open_local (NULL, &h, NULL, cmdline_credentials);
|
||||
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Unable to open local registry:%s \n", win_errstr(error));
|
||||
return 1;
|
||||
}
|
||||
|
||||
h = reg_common_open_local(cmdline_credentials);
|
||||
}
|
||||
|
||||
if (h == NULL && start_key == NULL)
|
||||
return 1;
|
||||
|
||||
poptFreeContext(pc);
|
||||
|
||||
error = WERR_OK;
|
||||
|
||||
if (root != NULL) {
|
||||
print_tree(0, root, fullpath, no_values);
|
||||
if (start_key != NULL) {
|
||||
print_tree(0, start_key, "", fullpath, no_values);
|
||||
} else {
|
||||
for(i = 0; reg_predefined_keys[i].handle; i++) {
|
||||
error = reg_get_predefined_key(h, reg_predefined_keys[i].handle, &root);
|
||||
error = reg_get_predefined_key(h, reg_predefined_keys[i].handle,
|
||||
&start_key);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
fprintf(stderr, "Skipping %s\n", reg_predefined_keys[i].name);
|
||||
fprintf(stderr, "Skipping %s: %s\n", reg_predefined_keys[i].name,
|
||||
win_errstr(error));
|
||||
continue;
|
||||
}
|
||||
SMB_ASSERT(root);
|
||||
print_tree(0, root, fullpath, no_values);
|
||||
SMB_ASSERT(start_key != NULL);
|
||||
print_tree(0, start_key, reg_predefined_keys[i].name, fullpath,
|
||||
no_values);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Transparent registry backend handling
|
||||
Copyright (C) Jelmer Vernooij 2003-2004.
|
||||
Copyright (C) Jelmer Vernooij 2003-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
|
||||
@ -50,27 +50,30 @@ _PUBLIC_ const char *str_regtype(int type)
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
_PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type, DATA_BLOB *data)
|
||||
_PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type,
|
||||
const DATA_BLOB data)
|
||||
{
|
||||
char *ret = NULL;
|
||||
|
||||
if(data->length == 0) return talloc_strdup(mem_ctx, "");
|
||||
if (data.length == 0)
|
||||
return talloc_strdup(mem_ctx, "");
|
||||
|
||||
switch (type) {
|
||||
case REG_EXPAND_SZ:
|
||||
case REG_SZ:
|
||||
convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, data->data, data->length, (void **)&ret);
|
||||
convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, data.data, data.length,
|
||||
(void **)&ret);
|
||||
return ret;
|
||||
|
||||
case REG_BINARY:
|
||||
ret = data_blob_hex_string(mem_ctx, data);
|
||||
ret = data_blob_hex_string(mem_ctx, &data);
|
||||
return ret;
|
||||
|
||||
case REG_DWORD:
|
||||
if (*(int *)data->data == 0)
|
||||
if (*(int *)data.data == 0)
|
||||
return talloc_strdup(mem_ctx, "0");
|
||||
|
||||
return talloc_asprintf(mem_ctx, "0x%x", *(int *)data->data);
|
||||
return talloc_asprintf(mem_ctx, "0x%x", *(int *)data.data);
|
||||
|
||||
case REG_MULTI_SZ:
|
||||
/* FIXME */
|
||||
@ -84,9 +87,13 @@ _PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type, DATA_BLOB
|
||||
}
|
||||
|
||||
/** Generate a string that describes a registry value */
|
||||
_PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx, struct registry_value *val)
|
||||
_PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx, const char *name,
|
||||
uint32_t data_type,
|
||||
const DATA_BLOB data)
|
||||
{
|
||||
return talloc_asprintf(mem_ctx, "%s = %s : %s", val->name?val->name:"<No Name>", str_regtype(val->data_type), reg_val_data_string(mem_ctx, val->data_type, &val->data));
|
||||
return talloc_asprintf(mem_ctx, "%s = %s : %s", name?name:"<No Name>",
|
||||
str_regtype(data_type),
|
||||
reg_val_data_string(mem_ctx, data_type, data));
|
||||
}
|
||||
|
||||
_PUBLIC_ BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *data_str, uint32_t *type, DATA_BLOB *data)
|
||||
@ -136,29 +143,6 @@ _PUBLIC_ BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const
|
||||
return True;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace all \'s with /'s
|
||||
*/
|
||||
char *reg_path_win2unix(char *path)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; path[i]; i++) {
|
||||
if(path[i] == '\\') path[i] = '/';
|
||||
}
|
||||
return path;
|
||||
}
|
||||
/**
|
||||
* Replace all /'s with \'s
|
||||
*/
|
||||
char *reg_path_unix2win(char *path)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; path[i]; i++) {
|
||||
if(path[i] == '/') path[i] = '\\';
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/** Open a key by name (including the predefined key name!) */
|
||||
WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result)
|
||||
{
|
||||
@ -167,14 +151,16 @@ WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, co
|
||||
int predeflength;
|
||||
char *predefname;
|
||||
|
||||
if(strchr(name, '\\')) predeflength = strchr(name, '\\')-name;
|
||||
else predeflength = strlen(name);
|
||||
if (strchr(name, '\\') != NULL)
|
||||
predeflength = strchr(name, '\\')-name;
|
||||
else
|
||||
predeflength = strlen(name);
|
||||
|
||||
predefname = talloc_strndup(mem_ctx, name, predeflength);
|
||||
error = reg_get_predefined_key_by_name(handle, predefname, &predef);
|
||||
talloc_free(predefname);
|
||||
|
||||
if(!W_ERROR_IS_OK(error)) {
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -186,7 +172,9 @@ WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, co
|
||||
}
|
||||
}
|
||||
|
||||
static WERROR get_abs_parent(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, struct registry_key **parent, const char **name)
|
||||
static WERROR get_abs_parent(TALLOC_CTX *mem_ctx, struct registry_context *ctx,
|
||||
const char *path, struct registry_key **parent,
|
||||
const char **name)
|
||||
{
|
||||
char *parent_name;
|
||||
WERROR error;
|
||||
@ -195,14 +183,14 @@ static WERROR get_abs_parent(TALLOC_CTX *mem_ctx, struct registry_context *ctx,
|
||||
return WERR_FOOBAR;
|
||||
}
|
||||
|
||||
parent_name = talloc_strndup(mem_ctx, path, strrchr(path, '\\')-1-path);
|
||||
parent_name = talloc_strndup(mem_ctx, path, strrchr(path, '\\')-path);
|
||||
|
||||
error = reg_open_key_abs(mem_ctx, ctx, parent_name, parent);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
return error;
|
||||
}
|
||||
|
||||
*name = talloc_strdup(mem_ctx, strchr(path, '\\')+1);
|
||||
*name = talloc_strdup(mem_ctx, strrchr(path, '\\')+1);
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
@ -228,20 +216,27 @@ WERROR reg_key_del_abs(struct registry_context *ctx, const char *path)
|
||||
return error;
|
||||
}
|
||||
|
||||
WERROR reg_key_add_abs(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, uint32_t access_mask, struct security_descriptor *sec_desc, struct registry_key **result)
|
||||
WERROR reg_key_add_abs(TALLOC_CTX *mem_ctx, struct registry_context *ctx,
|
||||
const char *path, uint32_t access_mask,
|
||||
struct security_descriptor *sec_desc,
|
||||
struct registry_key **result)
|
||||
{
|
||||
struct registry_key *parent;
|
||||
const char *n;
|
||||
WERROR error;
|
||||
|
||||
if (!strchr(path, '\\')) {
|
||||
return WERR_FOOBAR;
|
||||
return WERR_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
error = get_abs_parent(mem_ctx, ctx, path, &parent, &n);
|
||||
if (W_ERROR_IS_OK(error)) {
|
||||
error = reg_key_add_name(mem_ctx, parent, n, access_mask, sec_desc, result);
|
||||
if (!W_ERROR_IS_OK(error)) {
|
||||
DEBUG(2, ("Opening parent of %s failed with %s\n", path,
|
||||
win_errstr(error)));
|
||||
return error;
|
||||
}
|
||||
|
||||
error = reg_key_add_name(mem_ctx, parent, n, NULL, sec_desc, result);
|
||||
|
||||
return error;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Registry interface
|
||||
Copyright (C) Jelmer Vernooij 2004.
|
||||
Copyright (C) Jelmer Vernooij 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
|
||||
@ -26,8 +26,6 @@ static WERROR wine_open_reg (struct registry_hive *h, struct registry_key **key)
|
||||
/* FIXME: Open h->location and mmap it */
|
||||
}
|
||||
|
||||
|
||||
|
||||
static REG_OPS reg_backend_wine = {
|
||||
.name = "wine",
|
||||
.open_hive = wine_open_reg,
|
@ -28,7 +28,7 @@
|
||||
/*******************************************************************
|
||||
Close the low 3 fd's and open dev/null in their place.
|
||||
********************************************************************/
|
||||
static void close_low_fds(BOOL stderr_too)
|
||||
static void close_low_fds(bool stderr_too)
|
||||
{
|
||||
#ifndef VALGRIND
|
||||
int fd;
|
||||
@ -65,7 +65,7 @@ static void close_low_fds(BOOL stderr_too)
|
||||
Become a daemon, discarding the controlling terminal.
|
||||
**/
|
||||
|
||||
_PUBLIC_ void become_daemon(BOOL Fork)
|
||||
_PUBLIC_ void become_daemon(bool Fork)
|
||||
{
|
||||
if (Fork) {
|
||||
if (fork()) {
|
||||
@ -87,7 +87,7 @@ _PUBLIC_ void become_daemon(BOOL Fork)
|
||||
#endif /* HAVE_SETSID */
|
||||
|
||||
/* Close fd's 0,1,2. Needed if started by rsh */
|
||||
close_low_fds(False); /* Don't close stderr, let the debug system
|
||||
close_low_fds(false); /* Don't close stderr, let the debug system
|
||||
attach it to the logfile */
|
||||
}
|
||||
|
||||
|
@ -59,11 +59,12 @@ _PUBLIC_ struct dcesrv_handle *dcesrv_handle_new(struct dcesrv_connection_contex
|
||||
return h;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
find an internal handle given a wire handle. If the wire handle is NULL then
|
||||
allocate a new handle
|
||||
*/
|
||||
_PUBLIC_ struct dcesrv_handle *dcesrv_handle_fetch(struct dcesrv_connection_context *context,
|
||||
_PUBLIC_ struct dcesrv_handle *dcesrv_handle_fetch(
|
||||
struct dcesrv_connection_context *context,
|
||||
struct policy_handle *p,
|
||||
uint8_t handle_type)
|
||||
{
|
||||
|
@ -28,14 +28,20 @@
|
||||
|
||||
enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY };
|
||||
|
||||
static NTSTATUS dcerpc_winreg_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
|
||||
static NTSTATUS dcerpc_winreg_bind(struct dcesrv_call_state *dce_call,
|
||||
const struct dcesrv_interface *iface)
|
||||
{
|
||||
struct registry_context *ctx;
|
||||
WERROR err;
|
||||
|
||||
err = reg_open_local(dce_call->context,
|
||||
err = reg_open_samba(dce_call->context,
|
||||
&ctx, dce_call->conn->auth_state.session_info, NULL);
|
||||
|
||||
if (!W_ERROR_IS_OK(err)) {
|
||||
DEBUG(0, ("Error opening registry: %s\n", win_errstr(err)));
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
dce_call->context->private = ctx;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
@ -43,7 +49,9 @@ static NTSTATUS dcerpc_winreg_bind(struct dcesrv_call_state *dce_call, const str
|
||||
|
||||
#define DCESRV_INTERFACE_WINREG_BIND dcerpc_winreg_bind
|
||||
|
||||
static WERROR dcesrv_winreg_openhive (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, uint32_t hkey, struct policy_handle **outh)
|
||||
static WERROR dcesrv_winreg_openhive(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx, uint32_t hkey,
|
||||
struct policy_handle **outh)
|
||||
{
|
||||
struct registry_context *ctx = dce_call->context->private;
|
||||
struct dcesrv_handle *h;
|
||||
@ -79,8 +87,9 @@ func_winreg_OpenHive(HKPN,HKEY_PERFORMANCE_NLSTEXT)
|
||||
/*
|
||||
winreg_CloseKey
|
||||
*/
|
||||
static WERROR dcesrv_winreg_CloseKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_CloseKey *r)
|
||||
static WERROR dcesrv_winreg_CloseKey(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_CloseKey *r)
|
||||
{
|
||||
struct dcesrv_handle *h;
|
||||
|
||||
@ -93,12 +102,12 @@ static WERROR dcesrv_winreg_CloseKey(struct dcesrv_call_state *dce_call, TALLOC_
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
winreg_CreateKey
|
||||
*/
|
||||
static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_CreateKey *r)
|
||||
static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_CreateKey *r)
|
||||
{
|
||||
struct dcesrv_handle *h, *newh;
|
||||
WERROR error;
|
||||
@ -124,10 +133,9 @@ static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call, TALLOC
|
||||
}
|
||||
}
|
||||
|
||||
error = reg_key_add_name(newh, (struct registry_key *)h->data, r->in.name.name,
|
||||
r->in.access_mask,
|
||||
r->in.secdesc?&sd:NULL,
|
||||
(struct registry_key **)&newh->data);
|
||||
error = reg_key_add_name(newh, (struct registry_key *)h->data,
|
||||
r->in.name.name, NULL, r->in.secdesc?&sd:NULL,
|
||||
(struct registry_key **)&newh->data);
|
||||
if (W_ERROR_IS_OK(error)) {
|
||||
r->out.new_handle = &newh->wire_handle;
|
||||
} else {
|
||||
@ -141,8 +149,9 @@ static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call, TALLOC
|
||||
/*
|
||||
winreg_DeleteKey
|
||||
*/
|
||||
static WERROR dcesrv_winreg_DeleteKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_DeleteKey *r)
|
||||
static WERROR dcesrv_winreg_DeleteKey(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_DeleteKey *r)
|
||||
{
|
||||
struct dcesrv_handle *h;
|
||||
|
||||
@ -155,8 +164,9 @@ static WERROR dcesrv_winreg_DeleteKey(struct dcesrv_call_state *dce_call, TALLOC
|
||||
/*
|
||||
winreg_DeleteValue
|
||||
*/
|
||||
static WERROR dcesrv_winreg_DeleteValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_DeleteValue *r)
|
||||
static WERROR dcesrv_winreg_DeleteValue(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_DeleteValue *r)
|
||||
{
|
||||
struct dcesrv_handle *h;
|
||||
struct registry_key *key;
|
||||
@ -172,25 +182,29 @@ static WERROR dcesrv_winreg_DeleteValue(struct dcesrv_call_state *dce_call, TALL
|
||||
/*
|
||||
winreg_EnumKey
|
||||
*/
|
||||
static WERROR dcesrv_winreg_EnumKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_EnumKey *r)
|
||||
static WERROR dcesrv_winreg_EnumKey(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_EnumKey *r)
|
||||
{
|
||||
struct dcesrv_handle *h;
|
||||
struct registry_key *key;
|
||||
const char *name;
|
||||
NTTIME last_mod;
|
||||
|
||||
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
|
||||
|
||||
r->out.result = reg_key_get_subkey_by_index(mem_ctx, (struct registry_key *)h->data, r->in.enum_index, &key);
|
||||
r->out.result = reg_key_get_subkey_by_index(mem_ctx,
|
||||
(struct registry_key *)h->data, r->in.enum_index,
|
||||
&name, NULL, &last_mod);
|
||||
|
||||
if (W_ERROR_IS_OK(r->out.result)) {
|
||||
if (2*strlen_m_term(key->name) > r->in.name->size) {
|
||||
if (2*strlen_m_term(name) > r->in.name->size) {
|
||||
return WERR_MORE_DATA;
|
||||
}
|
||||
r->out.name->length = 2*strlen_m_term(key->name);
|
||||
r->out.name->name = key->name;
|
||||
r->out.name->length = 2*strlen_m_term(name);
|
||||
r->out.name->name = name;
|
||||
r->out.keyclass = talloc_zero(mem_ctx, struct winreg_StringBuf);
|
||||
if (r->in.last_changed_time) {
|
||||
r->out.last_changed_time = &key->last_mod;
|
||||
r->out.last_changed_time = &last_mod;
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,19 +215,24 @@ static WERROR dcesrv_winreg_EnumKey(struct dcesrv_call_state *dce_call, TALLOC_C
|
||||
/*
|
||||
winreg_EnumValue
|
||||
*/
|
||||
static WERROR dcesrv_winreg_EnumValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_EnumValue *r)
|
||||
static WERROR dcesrv_winreg_EnumValue(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_EnumValue *r)
|
||||
{
|
||||
struct dcesrv_handle *h;
|
||||
struct registry_key *key;
|
||||
struct registry_value *value;
|
||||
WERROR result;
|
||||
const char *data_name;
|
||||
uint32_t data_type;
|
||||
DATA_BLOB data;
|
||||
|
||||
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
|
||||
|
||||
key = h->data;
|
||||
|
||||
result = reg_key_get_value_by_index(mem_ctx, key, r->in.enum_index, &value);
|
||||
result = reg_key_get_value_by_index(mem_ctx, key, r->in.enum_index,
|
||||
&data_name,
|
||||
&data_type, &data);
|
||||
if (!W_ERROR_IS_OK(result)) {
|
||||
return result;
|
||||
}
|
||||
@ -222,32 +241,32 @@ static WERROR dcesrv_winreg_EnumValue(struct dcesrv_call_state *dce_call, TALLOC
|
||||
want that back */
|
||||
if (r->in.type != NULL) {
|
||||
r->out.type = talloc(mem_ctx, enum winreg_Type);
|
||||
*r->out.type = value->data_type;
|
||||
*r->out.type = data_type;
|
||||
}
|
||||
|
||||
/* check the client has enough room for the value */
|
||||
if (r->in.value != NULL &&
|
||||
r->in.size != NULL &&
|
||||
value->data.length > *r->in.size) {
|
||||
data.length > *r->in.size) {
|
||||
return WERR_MORE_DATA;
|
||||
}
|
||||
|
||||
/* and enough room for the name */
|
||||
if (r->in.name->size < 2*strlen_m_term(value->name)) {
|
||||
if (r->in.name->size < 2*strlen_m_term(data_name)) {
|
||||
return WERR_MORE_DATA;
|
||||
}
|
||||
|
||||
r->out.name->name = value->name;
|
||||
r->out.name->length = 2*strlen_m_term(value->name);
|
||||
r->out.name->size = 2*strlen_m_term(value->name);
|
||||
r->out.name->name = data_name;
|
||||
r->out.name->length = 2*strlen_m_term(data_name);
|
||||
r->out.name->size = 2*strlen_m_term(data_name);
|
||||
|
||||
if (r->in.value) {
|
||||
r->out.value = value->data.data;
|
||||
r->out.value = data.data;
|
||||
}
|
||||
|
||||
if (r->in.size) {
|
||||
r->out.size = talloc(mem_ctx, uint32_t);
|
||||
*r->out.size = value->data.length;
|
||||
*r->out.size = data.length;
|
||||
r->out.length = r->out.size;
|
||||
}
|
||||
|
||||
@ -258,8 +277,9 @@ static WERROR dcesrv_winreg_EnumValue(struct dcesrv_call_state *dce_call, TALLOC
|
||||
/*
|
||||
winreg_FlushKey
|
||||
*/
|
||||
static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_FlushKey *r)
|
||||
static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_FlushKey *r)
|
||||
{
|
||||
struct dcesrv_handle *h;
|
||||
|
||||
@ -272,8 +292,9 @@ static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call, TALLOC_
|
||||
/*
|
||||
winreg_GetKeySecurity
|
||||
*/
|
||||
static WERROR dcesrv_winreg_GetKeySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_GetKeySecurity *r)
|
||||
static WERROR dcesrv_winreg_GetKeySecurity(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_GetKeySecurity *r)
|
||||
{
|
||||
struct dcesrv_handle *h;
|
||||
|
||||
@ -286,8 +307,9 @@ static WERROR dcesrv_winreg_GetKeySecurity(struct dcesrv_call_state *dce_call, T
|
||||
/*
|
||||
winreg_LoadKey
|
||||
*/
|
||||
static WERROR dcesrv_winreg_LoadKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_LoadKey *r)
|
||||
static WERROR dcesrv_winreg_LoadKey(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_LoadKey *r)
|
||||
{
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
@ -296,8 +318,9 @@ static WERROR dcesrv_winreg_LoadKey(struct dcesrv_call_state *dce_call, TALLOC_C
|
||||
/*
|
||||
winreg_NotifyChangeKeyValue
|
||||
*/
|
||||
static WERROR dcesrv_winreg_NotifyChangeKeyValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_NotifyChangeKeyValue *r)
|
||||
static WERROR dcesrv_winreg_NotifyChangeKeyValue(
|
||||
struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx, struct winreg_NotifyChangeKeyValue *r)
|
||||
{
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
@ -306,8 +329,9 @@ static WERROR dcesrv_winreg_NotifyChangeKeyValue(struct dcesrv_call_state *dce_c
|
||||
/*
|
||||
winreg_OpenKey
|
||||
*/
|
||||
static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_OpenKey *r)
|
||||
static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_OpenKey *r)
|
||||
{
|
||||
struct dcesrv_handle *h, *newh;
|
||||
WERROR result;
|
||||
@ -336,82 +360,66 @@ static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call, TALLOC_C
|
||||
/*
|
||||
winreg_QueryInfoKey
|
||||
*/
|
||||
static WERROR dcesrv_winreg_QueryInfoKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_QueryInfoKey *r)
|
||||
static WERROR dcesrv_winreg_QueryInfoKey(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_QueryInfoKey *r)
|
||||
{
|
||||
struct dcesrv_handle *h;
|
||||
struct registry_key *k;
|
||||
WERROR ret;
|
||||
const char *classname;
|
||||
|
||||
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
|
||||
|
||||
k = h->data;
|
||||
|
||||
ret = reg_key_num_subkeys(k, r->out.num_subkeys);
|
||||
if (!W_ERROR_IS_OK(ret)) {
|
||||
return ret;
|
||||
}
|
||||
ret = reg_key_get_info(mem_ctx, k, &classname, r->out.num_subkeys,
|
||||
r->out.num_values, r->out.last_changed_time);
|
||||
|
||||
ret = reg_key_num_values(k, r->out.num_values);
|
||||
if (!W_ERROR_IS_OK(ret)) {
|
||||
return ret;
|
||||
}
|
||||
if (r->out.classname != NULL)
|
||||
r->out.classname->name = classname;
|
||||
|
||||
ret = reg_key_subkeysizes(k, r->out.max_subkeysize, r->out.max_subkeylen);
|
||||
if (!W_ERROR_IS_OK(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reg_key_valuesizes(k, r->out.max_valnamelen, r->out.max_valbufsize);
|
||||
if (!W_ERROR_IS_OK(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
r->out.secdescsize = 0; /* FIXME */
|
||||
ZERO_STRUCT(r->out.last_changed_time); /* FIXME */
|
||||
if (!W_ERROR_IS_OK(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
return WERR_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
winreg_QueryValue
|
||||
*/
|
||||
static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_QueryValue *r)
|
||||
static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_QueryValue *r)
|
||||
{
|
||||
struct dcesrv_handle *h;
|
||||
struct registry_key *key;
|
||||
struct registry_value *val;
|
||||
uint32_t value_type;
|
||||
DATA_BLOB value_data;
|
||||
WERROR result;
|
||||
|
||||
DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
|
||||
|
||||
key = h->data;
|
||||
|
||||
result = reg_key_get_value_by_name(mem_ctx, key, r->in.value_name.name, &val);
|
||||
result = reg_key_get_value_by_name(mem_ctx, key, r->in.value_name.name,
|
||||
&value_type, &value_data);
|
||||
|
||||
if (!W_ERROR_IS_OK(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Just asking for the size of the buffer */
|
||||
r->out.type = (enum winreg_Type *)&val->data_type;
|
||||
r->out.type = &value_type;
|
||||
r->out.length = talloc(mem_ctx, uint32_t);
|
||||
if (!r->out.length) {
|
||||
return WERR_NOMEM;
|
||||
}
|
||||
*r->out.length = val->data.length;
|
||||
if (!r->in.data) {
|
||||
*r->out.length = value_data.length;
|
||||
if (r->in.data == NULL) {
|
||||
r->out.size = talloc(mem_ctx, uint32_t);
|
||||
*r->out.size = val->data.length;
|
||||
*r->out.size = value_data.length;
|
||||
} else {
|
||||
r->out.size = r->in.size;
|
||||
r->out.data = val->data.data;
|
||||
r->out.data = value_data.data;
|
||||
}
|
||||
|
||||
return WERR_OK;
|
||||
@ -421,8 +429,9 @@ static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call, TALLO
|
||||
/*
|
||||
winreg_ReplaceKey
|
||||
*/
|
||||
static WERROR dcesrv_winreg_ReplaceKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_ReplaceKey *r)
|
||||
static WERROR dcesrv_winreg_ReplaceKey(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_ReplaceKey *r)
|
||||
{
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
@ -431,8 +440,9 @@ static WERROR dcesrv_winreg_ReplaceKey(struct dcesrv_call_state *dce_call, TALLO
|
||||
/*
|
||||
winreg_RestoreKey
|
||||
*/
|
||||
static WERROR dcesrv_winreg_RestoreKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_RestoreKey *r)
|
||||
static WERROR dcesrv_winreg_RestoreKey(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_RestoreKey *r)
|
||||
{
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
@ -441,8 +451,9 @@ static WERROR dcesrv_winreg_RestoreKey(struct dcesrv_call_state *dce_call, TALLO
|
||||
/*
|
||||
winreg_SaveKey
|
||||
*/
|
||||
static WERROR dcesrv_winreg_SaveKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_SaveKey *r)
|
||||
static WERROR dcesrv_winreg_SaveKey(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_SaveKey *r)
|
||||
{
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
@ -451,8 +462,9 @@ static WERROR dcesrv_winreg_SaveKey(struct dcesrv_call_state *dce_call, TALLOC_C
|
||||
/*
|
||||
winreg_SetKeySecurity
|
||||
*/
|
||||
static WERROR dcesrv_winreg_SetKeySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_SetKeySecurity *r)
|
||||
static WERROR dcesrv_winreg_SetKeySecurity(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_SetKeySecurity *r)
|
||||
{
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
@ -461,8 +473,9 @@ static WERROR dcesrv_winreg_SetKeySecurity(struct dcesrv_call_state *dce_call, T
|
||||
/*
|
||||
winreg_SetValue
|
||||
*/
|
||||
static WERROR dcesrv_winreg_SetValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_SetValue *r)
|
||||
static WERROR dcesrv_winreg_SetValue(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_SetValue *r)
|
||||
{
|
||||
struct dcesrv_handle *h;
|
||||
struct registry_key *key;
|
||||
@ -488,8 +501,9 @@ static WERROR dcesrv_winreg_SetValue(struct dcesrv_call_state *dce_call, TALLOC_
|
||||
/*
|
||||
winreg_UnLoadKey
|
||||
*/
|
||||
static WERROR dcesrv_winreg_UnLoadKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_UnLoadKey *r)
|
||||
static WERROR dcesrv_winreg_UnLoadKey(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_UnLoadKey *r)
|
||||
{
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
@ -498,8 +512,9 @@ static WERROR dcesrv_winreg_UnLoadKey(struct dcesrv_call_state *dce_call, TALLOC
|
||||
/*
|
||||
winreg_InitiateSystemShutdown
|
||||
*/
|
||||
static WERROR dcesrv_winreg_InitiateSystemShutdown(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_InitiateSystemShutdown *r)
|
||||
static WERROR dcesrv_winreg_InitiateSystemShutdown(
|
||||
struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_InitiateSystemShutdown *r)
|
||||
{
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
@ -508,8 +523,9 @@ static WERROR dcesrv_winreg_InitiateSystemShutdown(struct dcesrv_call_state *dce
|
||||
/*
|
||||
winreg_AbortSystemShutdown
|
||||
*/
|
||||
static WERROR dcesrv_winreg_AbortSystemShutdown(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_AbortSystemShutdown *r)
|
||||
static WERROR dcesrv_winreg_AbortSystemShutdown(
|
||||
struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_AbortSystemShutdown *r)
|
||||
{
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
@ -518,8 +534,9 @@ static WERROR dcesrv_winreg_AbortSystemShutdown(struct dcesrv_call_state *dce_ca
|
||||
/*
|
||||
winreg_GetVersion
|
||||
*/
|
||||
static WERROR dcesrv_winreg_GetVersion(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_GetVersion *r)
|
||||
static WERROR dcesrv_winreg_GetVersion(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_GetVersion *r)
|
||||
{
|
||||
struct dcesrv_handle *h;
|
||||
|
||||
@ -537,8 +554,9 @@ static WERROR dcesrv_winreg_GetVersion(struct dcesrv_call_state *dce_call, TALLO
|
||||
/*
|
||||
winreg_QueryMultipleValues
|
||||
*/
|
||||
static WERROR dcesrv_winreg_QueryMultipleValues(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_QueryMultipleValues *r)
|
||||
static WERROR dcesrv_winreg_QueryMultipleValues(
|
||||
struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_QueryMultipleValues *r)
|
||||
{
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
@ -547,8 +565,9 @@ static WERROR dcesrv_winreg_QueryMultipleValues(struct dcesrv_call_state *dce_ca
|
||||
/*
|
||||
winreg_InitiateSystemShutdownEx
|
||||
*/
|
||||
static WERROR dcesrv_winreg_InitiateSystemShutdownEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_InitiateSystemShutdownEx *r)
|
||||
static WERROR dcesrv_winreg_InitiateSystemShutdownEx(
|
||||
struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_InitiateSystemShutdownEx *r)
|
||||
{
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
@ -557,8 +576,9 @@ static WERROR dcesrv_winreg_InitiateSystemShutdownEx(struct dcesrv_call_state *d
|
||||
/*
|
||||
winreg_SaveKeyEx
|
||||
*/
|
||||
static WERROR dcesrv_winreg_SaveKeyEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_SaveKeyEx *r)
|
||||
static WERROR dcesrv_winreg_SaveKeyEx(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct winreg_SaveKeyEx *r)
|
||||
{
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
@ -567,8 +587,9 @@ static WERROR dcesrv_winreg_SaveKeyEx(struct dcesrv_call_state *dce_call, TALLOC
|
||||
/*
|
||||
winreg_QueryMultipleValues2
|
||||
*/
|
||||
static WERROR dcesrv_winreg_QueryMultipleValues2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_QueryMultipleValues2 *r)
|
||||
static WERROR dcesrv_winreg_QueryMultipleValues2(
|
||||
struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct winreg_QueryMultipleValues2 *r)
|
||||
{
|
||||
return WERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
@ -46,5 +46,4 @@ RPC-SVCCTL
|
||||
RPC-DSSYNC
|
||||
RPC-EPMAPPER
|
||||
RPC-INITSHUTDOWN
|
||||
RPC-WINREG
|
||||
RPC-SAMSYNC
|
||||
|
@ -3,6 +3,8 @@
|
||||
LEX="$1"
|
||||
SRC="$2"
|
||||
DEST="$3"
|
||||
shift 3
|
||||
ARGS="$*"
|
||||
|
||||
dir=`dirname $SRC`
|
||||
file=`basename $SRC`
|
||||
@ -29,12 +31,15 @@ if [ -r $DEST ]; then
|
||||
fi
|
||||
fi
|
||||
TOP=`pwd`
|
||||
if cd $dir && $LEX $file; then
|
||||
if cd $dir && $LEX $ARGS $file; then
|
||||
if [ -r $base.yy.c ];then
|
||||
# we must guarantee that config.h comes first
|
||||
echo "#include \"config.h\"" > $base.c
|
||||
sed '/^#/ s|$base.yy\.c|$DEST|' $base.yy.c >> $base.c
|
||||
rm -f $base.yy.c
|
||||
elif [ ! -r base.c ]; then
|
||||
echo "$base.c nor $base.yy.c generated."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
cd $TOP
|
||||
|
@ -575,8 +575,6 @@ static int ejs_ldb_attach_dsdb_schema_from_ldif(MprVarHandle eid, int argc, char
|
||||
{
|
||||
struct ldb_context *ldb;
|
||||
WERROR status;
|
||||
char *pf_name;
|
||||
char *df_name;
|
||||
const char *pf;
|
||||
const char *df;
|
||||
|
||||
|
17
source4/setup/provision.reg
Normal file
17
source4/setup/provision.reg
Normal file
@ -0,0 +1,17 @@
|
||||
REGEDIT4
|
||||
|
||||
[HKEY_LOCAL_MACHINE]
|
||||
|
||||
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\ProductOptions]
|
||||
ProductType="LanmanNT"
|
||||
|
||||
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Print]
|
||||
|
||||
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Server]
|
||||
|
||||
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Netlogon\Parameters]
|
||||
RefusePasswordChange=REG_DWORD:0
|
||||
|
||||
[HKEY_USERS]
|
||||
|
||||
[HKEY_CLASSES_ROOT]
|
@ -262,7 +262,7 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[
|
||||
|
||||
if (opt_daemon) {
|
||||
DEBUG(3,("Becoming a daemon.\n"));
|
||||
become_daemon(True);
|
||||
become_daemon(true);
|
||||
}
|
||||
|
||||
cleanup_tmp_files();
|
||||
@ -286,9 +286,6 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[
|
||||
|
||||
gensec_init(); /* FIXME: */
|
||||
|
||||
registry_init(); /* FIXME: maybe run this in the initialization function
|
||||
of the winreg RPC server instead? */
|
||||
|
||||
ntptr_init(); /* FIXME: maybe run this in the initialization function
|
||||
of the spoolss RPC server instead? */
|
||||
|
||||
|
@ -23,6 +23,9 @@ OBJ_FILES = \
|
||||
../../lib/socket_wrapper/testsuite.o \
|
||||
irpc.o \
|
||||
../../lib/registry/tests/generic.o \
|
||||
../../lib/registry/tests/hive.o \
|
||||
../../lib/registry/tests/diff.o \
|
||||
../../lib/registry/tests/registry.o \
|
||||
resolve.o \
|
||||
../../lib/util/tests/strlist.o \
|
||||
../../lib/util/tests/file.o \
|
||||
|
@ -457,7 +457,8 @@ static const uint8_t getkeysecurity_in_data[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static bool getkeysecurity_in_check(struct torture_context *tctx, struct winreg_GetKeySecurity *r)
|
||||
static bool getkeysecurity_in_check(struct torture_context *tctx,
|
||||
struct winreg_GetKeySecurity *r)
|
||||
{
|
||||
/* FIXME: Handle */
|
||||
torture_assert_int_equal(tctx, r->in.sec_info, 2, "sec info");
|
||||
@ -474,7 +475,8 @@ static const uint8_t getkeysecurity_out_data[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static bool getkeysecurity_out_check(struct torture_context *tctx, struct winreg_GetKeySecurity *r)
|
||||
static bool getkeysecurity_out_check(struct torture_context *tctx,
|
||||
struct winreg_GetKeySecurity *r)
|
||||
{
|
||||
torture_assert_int_equal(tctx, r->in.sd->size, 20, "sd size");
|
||||
torture_assert_int_equal(tctx, r->in.sd->len, 20, "sd len");
|
||||
|
@ -575,11 +575,11 @@ static bool test_handles_drsuapi(struct torture_context *torture)
|
||||
}
|
||||
|
||||
|
||||
struct torture_suite *torture_rpc_handles(void)
|
||||
struct torture_suite *torture_rpc_handles(TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct torture_suite *suite;
|
||||
|
||||
suite = torture_suite_create(talloc_autofree_context(), "HANDLES");
|
||||
suite = torture_suite_create(mem_ctx, "HANDLES");
|
||||
torture_suite_add_simple_test(suite, "lsarpc", test_handles_lsa);
|
||||
torture_suite_add_simple_test(suite, "lsarpc-shared", test_handles_lsa_shared);
|
||||
torture_suite_add_simple_test(suite, "samr", test_handles_samr);
|
||||
|
@ -134,6 +134,17 @@ static bool torture_rpc_wrap_test(struct torture_context *tctx,
|
||||
return fn(tctx, (struct dcerpc_pipe *)tcase->data);
|
||||
}
|
||||
|
||||
static bool torture_rpc_wrap_test_ex(struct torture_context *tctx,
|
||||
struct torture_tcase *tcase,
|
||||
struct torture_test *test)
|
||||
{
|
||||
bool (*fn) (struct torture_context *, struct dcerpc_pipe *, const void *);
|
||||
|
||||
fn = test->fn;
|
||||
|
||||
return fn(tctx, (struct dcerpc_pipe *)tcase->data, test->data);
|
||||
}
|
||||
|
||||
_PUBLIC_ struct torture_test *torture_rpc_tcase_add_test(
|
||||
struct torture_tcase *tcase,
|
||||
const char *name,
|
||||
@ -155,6 +166,29 @@ _PUBLIC_ struct torture_test *torture_rpc_tcase_add_test(
|
||||
return test;
|
||||
}
|
||||
|
||||
_PUBLIC_ struct torture_test *torture_rpc_tcase_add_test_ex(
|
||||
struct torture_tcase *tcase,
|
||||
const char *name,
|
||||
bool (*fn) (struct torture_context *, struct dcerpc_pipe *,
|
||||
void *),
|
||||
void *userdata)
|
||||
{
|
||||
struct torture_test *test;
|
||||
|
||||
test = talloc(tcase, struct torture_test);
|
||||
|
||||
test->name = talloc_strdup(test, name);
|
||||
test->description = NULL;
|
||||
test->run = torture_rpc_wrap_test_ex;
|
||||
test->dangerous = false;
|
||||
test->data = userdata;
|
||||
test->fn = fn;
|
||||
|
||||
DLIST_ADD(tcase->tests, test);
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
NTSTATUS torture_rpc_init(void)
|
||||
{
|
||||
struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "RPC");
|
||||
@ -173,7 +207,8 @@ NTSTATUS torture_rpc_init(void)
|
||||
torture_suite_add_suite(suite, torture_rpc_eventlog());
|
||||
torture_suite_add_suite(suite, torture_rpc_atsvc());
|
||||
torture_suite_add_suite(suite, torture_rpc_wkssvc());
|
||||
torture_suite_add_suite(suite, torture_rpc_handles());
|
||||
torture_suite_add_suite(suite, torture_rpc_handles(suite));
|
||||
torture_suite_add_suite(suite, torture_rpc_winreg(suite));
|
||||
torture_suite_add_simple_test(suite, "SPOOLSS", torture_rpc_spoolss);
|
||||
torture_suite_add_simple_test(suite, "SAMR", torture_rpc_samr);
|
||||
torture_suite_add_simple_test(suite, "SAMR-USERS", torture_rpc_samr_users);
|
||||
@ -186,7 +221,6 @@ NTSTATUS torture_rpc_init(void)
|
||||
torture_suite_add_simple_test(suite, "SRVSVC", torture_rpc_srvsvc);
|
||||
torture_suite_add_simple_test(suite, "SVCCTL", torture_rpc_svcctl);
|
||||
torture_suite_add_simple_test(suite, "EPMAPPER", torture_rpc_epmapper);
|
||||
torture_suite_add_simple_test(suite, "WINREG", torture_rpc_winreg);
|
||||
torture_suite_add_simple_test(suite, "INITSHUTDOWN", torture_rpc_initshutdown);
|
||||
torture_suite_add_simple_test(suite, "OXIDRESOLVE", torture_rpc_oxidresolve);
|
||||
torture_suite_add_simple_test(suite, "REMACT", torture_rpc_remact);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -433,3 +433,37 @@ struct torture_suite *torture_find_suite(struct torture_suite *parent,
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool wrap_test_with_simple_test(struct torture_context *torture_ctx,
|
||||
struct torture_tcase *tcase,
|
||||
struct torture_test *test)
|
||||
{
|
||||
bool (*fn) (struct torture_context *, const void *tcase_data);
|
||||
|
||||
fn = test->fn;
|
||||
|
||||
return fn(torture_ctx, tcase->data);
|
||||
}
|
||||
|
||||
struct torture_test *torture_tcase_add_simple_test(
|
||||
struct torture_tcase *tcase,
|
||||
const char *name,
|
||||
bool (*run) (struct torture_context *test, const void *tcase_data))
|
||||
{
|
||||
struct torture_test *test;
|
||||
|
||||
test = talloc(tcase, struct torture_test);
|
||||
|
||||
test->name = talloc_strdup(test, name);
|
||||
test->description = NULL;
|
||||
test->run = wrap_test_with_simple_test;
|
||||
test->fn = run;
|
||||
test->data = NULL;
|
||||
test->dangerous = False;
|
||||
|
||||
DLIST_ADD_END(tcase->tests, test, struct torture_test *);
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
|
@ -165,6 +165,13 @@ struct torture_tcase *torture_suite_add_simple_tcase(
|
||||
bool (*run) (struct torture_context *test, const void *test_data),
|
||||
const void *data);
|
||||
|
||||
/* Convenience function that adds a test which only
|
||||
* gets the test case data */
|
||||
struct torture_test *torture_tcase_add_simple_test(
|
||||
struct torture_tcase *tcase,
|
||||
const char *name,
|
||||
bool (*run) (struct torture_context *test, const void *tcase_data));
|
||||
|
||||
/* Convenience wrapper that adds a test that doesn't need any
|
||||
* testcase data */
|
||||
struct torture_tcase *torture_suite_add_simple_test(
|
||||
@ -258,6 +265,20 @@ void torture_result(struct torture_context *test,
|
||||
talloc_free(__got); \
|
||||
} while(0)
|
||||
|
||||
#define torture_assert_file_contains(torture_ctx,filename,expected,cmt)\
|
||||
do { const char *__got, *__expected = (expected); \
|
||||
size_t __size; \
|
||||
__got = file_load(filename, *size, torture_ctx); \
|
||||
if (strcmp_safe(__got, __expected) != 0) { \
|
||||
torture_result(torture_ctx, TORTURE_FAIL, \
|
||||
__location__": %s contained:\n%sExpected: %s%s\n", \
|
||||
__got, __expected, cmt); \
|
||||
talloc_free(__got); \
|
||||
return false; \
|
||||
} \
|
||||
talloc_free(__got); \
|
||||
} while(0)
|
||||
|
||||
#define torture_assert_int_equal(torture_ctx,got,expected,cmt)\
|
||||
do { int __got = (got), __expected = (expected); \
|
||||
if (__got != __expected) { \
|
||||
|
@ -4,7 +4,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: qooxdoo framework\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2007-02-12 03:06+0100\n"
|
||||
"POT-Creation-Date: 2007-02-10 16:11+0100\n"
|
||||
"PO-Revision-Date: 2006-12-19 15:52+0100\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
|
Loading…
Reference in New Issue
Block a user