Skip to content
Permalink
Browse files Browse the repository at this point in the history
- ini-agent: added Write(.section_private.SECTION, BOOLEAN) (bnc#7136…
…61, CVE-2011-3177)

- system agent: added  Write(.target.string, [filename, mode],  content)

svn merge -r66758:66764 http://svn.opensuse.org/svn/yast/branches/SuSE-Code-11-SP2-Branch/core

svn path=/trunk/core/; revision=67117
  • Loading branch information
mvidner committed Jan 5, 2012
1 parent 41555de commit 7fe2e3d
Show file tree
Hide file tree
Showing 17 changed files with 239 additions and 42 deletions.
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
2.22.0
2.22.1
13 changes: 10 additions & 3 deletions agent-ini/doc/ag_ini.html
Expand Up @@ -280,7 +280,7 @@ <h4 id="params">Params:</h4>
<p>Then begin regexp is: ([^=]+)="([^"]*) and end regexp is
([^"]"). These are compared at the end so they are the last
possibility. But once we get into this "divided line" by accident,
it becomes greedy, so be carefull to forgotten ". If "multiline" is
it becomes greedy, so be carefull to forgotten &quot;. If "multiline" is
not present, this mechanism does not take in effect of course.</p>

<p>See also the option <a
Expand Down Expand Up @@ -473,7 +473,7 @@ <h3 id="sysconfig">Configuration file for sysconfig files (former rc files)</h3>
"comments": [ "^[ \t]*#.*$", "#.*", "^[ \t]*$", ],
"params" : [
$[
"match" : [ "([a-zA-Z0-9_]+)[ \t]*=[ \t]*\"([^\"]*)\"", "%s=\"%s\"" ],
"match" : [ "([a-zA-Z0-9_]+)[ \t]*=[ \t]*\"([^\&quot;]*)\"", "%s=\"%s\"" ],
"multiline" : [ "([a-zA-Z0-9_]+)[ \t]*=[ \t]*\"([^\"]*)", "([^\"]*)\"", ],
],
$[
Expand Down Expand Up @@ -533,6 +533,13 @@ <h3 id="access">Accessing keys</h3>
section was read by.</td>
</tr>

<tr>
<td>
<tt>.ini.section_private.<i>sectionname</i></tt></td>
<td>a boolean write-only property for sections corresponding to files.
If true, the file will not be readable by group and others.</td>
</tr>

<tr class="notimpl">
<td>
<tt>.ini.section_file.<i>sectionname</i>.<i>sectionname</i></tt></td>
Expand Down Expand Up @@ -694,7 +701,7 @@ <h3 id="ex.providers">Dialup providers (package providers)</h3>
],
"params" : [
$[
"match" : [ "^[ \t]*([^=]*[^ \t=])[ \t]*=[ \t]*(.*[^ \t]|)[ \t]*$" , "%s = ],
"match" : [ "^[ \t]*([^=]*[^ \t=])[ \t]*=[ \t]*(.*[^ \t]|)[ \t]*$" , "%s = %s" ],
],
]
)
Expand Down
2 changes: 1 addition & 1 deletion agent-ini/src/IniAgent.cc
Expand Up @@ -98,7 +98,7 @@ YCPBoolean IniAgent::Write(const YCPPath &path, const YCPValue& value, const YCP
else
{
if (( parser.repeatNames () && value->isList ()) ||
(!parser.repeatNames () && (value->isString () || value->isInteger())) ||
(!parser.repeatNames () && (value->isString () || value->isBoolean() || value->isInteger())) ||
path->component_str(0) == "all"
)
{
Expand Down
24 changes: 23 additions & 1 deletion agent-ini/src/IniFile.cc
Expand Up @@ -75,6 +75,19 @@ YCPInteger as_integer (const YCPValue& v, const char * context)
return YCPNull ();
}

/**
* Return the YCPBoolean or YCPNull if it is not one. Log an error.
*/
static
YCPBoolean as_boolean (const YCPValue& v, const char * context)
{
if (v->isBoolean ())
return v->asBoolean ();
ycp2error ("Expected a boolean for %s, got %s %s",
context, v->valuetype_str(), v->toString().c_str());
return YCPNull ();
}

void IniSection::initValue (const string&key,const string&val,const string&comment,int rb)
{
string k = ip->changeCase (key);
Expand Down Expand Up @@ -486,6 +499,9 @@ int IniSection::Write (const YCPPath&p, const YCPValue&v, bool rewrite)
return setSectionProp (p, v, 0, 1);
if (s == "st" || s == "section_type" || s == "sectiontype")
return setSectionProp (p, v, rewrite? 1:2, 1);
if (s == "section_private")
return setSectionProp (p, v, 3, 1);

return -1;
}

Expand Down Expand Up @@ -591,12 +607,18 @@ int IniSection::setSectionProp (const YCPPath&p,const YCPValue&in, int what, int
return -1;
s.setRewriteBy (i->value());
}
else {
else if (what == 2) {
YCPInteger i = as_integer (prop, "section_type");
if (i.isNull())
return -1;
s.setReadBy (i->value());
}
else if (what == 3) {
YCPBoolean b = as_boolean (prop, "section_private");
if (b.isNull())
return -1;
s.setPrivate (b->value());
}

if (xi != xe)
{
Expand Down
20 changes: 16 additions & 4 deletions agent-ini/src/IniFile.h
Expand Up @@ -241,6 +241,13 @@ class IniSection : public IniBase
*/
string end_comment;

/**
* It is effective only when the section corresponds to a file.
* The file will not be readable by group and others.
* bnc#713661
*/
bool is_private;

/** index to IniParser::rewrites for filename - section name mapping
* It appears that read_by was used for both purposes,
* causing bug (#19066).
Expand Down Expand Up @@ -435,7 +442,7 @@ class IniSection : public IniBase
IniSection (const IniParser *p)
: IniBase (-1),
ip (p),
end_comment (), rewrite_by(-1),
end_comment (), is_private(false), rewrite_by(-1),
container (), ivalues (), isections ()
{}

Expand All @@ -446,7 +453,7 @@ class IniSection : public IniBase
IniSection (const IniSection &s) :
IniBase (s),
ip (s.ip),
end_comment (s.end_comment), rewrite_by (s.rewrite_by),
end_comment (s.end_comment), is_private(s.is_private), rewrite_by (s.rewrite_by),
container (s.container)
{ reindex (); }

Expand All @@ -458,7 +465,9 @@ class IniSection : public IniBase
}
IniBase::operator = (s);
ip = s.ip;
end_comment = s.end_comment; rewrite_by = s.rewrite_by;
end_comment = s.end_comment;
is_private = s.is_private;
rewrite_by = s.rewrite_by;
container = s.container;

reindex ();
Expand All @@ -474,7 +483,7 @@ class IniSection : public IniBase
IniSection (const IniParser *p, string n)
: IniBase (n),
ip (p),
end_comment (), rewrite_by(0),
end_comment (), is_private(false), rewrite_by(0),
container(), ivalues (), isections ()
{}
/**
Expand Down Expand Up @@ -511,6 +520,9 @@ class IniSection : public IniBase
*/
int getSubSectionRewriteBy (const char*name);

void setPrivate(bool p) { is_private = p; }
bool isPrivate() const { return is_private; }

/**
* If there is no comment at the beginning and no values and no
* sections, it is better to set is as comment at the beginning.
Expand Down
55 changes: 28 additions & 27 deletions agent-ini/src/IniParser.cc
Expand Up @@ -965,19 +965,7 @@ int IniParser::write()
continue;
}
s.initReadBy ();
// ensure that the directories exist
Pathname pn (filename);
PathInfo::assert_dir (pn.dirname ());
ofstream of(filename.c_str());
if (!of.good())
{
bugs++;
y2error ("Can not open file %s for write", filename.c_str());
continue;
}
write_helper (s, of, 0);
s.clean();
of.close ();
bugs += write_file(filename, s);
}
else
{
Expand All @@ -997,24 +985,37 @@ int IniParser::write()
}
else
{
// ensure that the directories exist
Pathname pn (file);
PathInfo::assert_dir (pn.dirname ());
ofstream of(file.c_str());
if (!of.good())
{
y2error ("Can not open file %s for write", file.c_str());
return -1;
}

write_helper (inifile, of, 0);

of.close();
bugs += write_file(file, inifile);
timestamp = getTimeStamp ();
}
inifile.clean ();
return bugs ? -1 : 0;
}

// return 0 on success, like write
int IniParser::write_file(const string & filename, IniSection & section)
{
// ensure that the directories exist
Pathname pn(filename);
PathInfo::assert_dir (pn.dirname ());

mode_t file_umask = section.isPrivate()? 0077: 0022;
mode_t orig_umask = umask(file_umask);
// rewriting an existing file wouldnt change its mode
unlink(filename.c_str());

ofstream of(filename.c_str());
if (!of.good()) {
y2error ("Can not open file %s for write", filename.c_str());
return -1;
}

write_helper (section, of, 0);

of.close();
umask(orig_umask);
return 0;
}

int IniParser::write_helper(IniSection&ini, ofstream&of, int depth)
{
char * out_buffer;
Expand Down
4 changes: 4 additions & 0 deletions agent-ini/src/IniParser.h
Expand Up @@ -369,6 +369,10 @@ class IniParser
* Parse one ini file and build a structure of IniSection.
*/
int parse_helper(IniSection&ini);
/**
* Write one ini file.
*/
int write_file(const string & filename, IniSection & section);
/**
* Write one ini file.
*/
Expand Down
11 changes: 11 additions & 0 deletions agent-ini/testsuite/multi/private.err
@@ -0,0 +1,11 @@
[agent-ini] IniParser.cc(parse):XXX Rewriting multi/private.in.1.test to 1
[agent-ini] IniParser.cc(parse):XXX Rewriting multi/private.in.2.test to 2
[agent-ini] IniFile.cc(setMyValue):XXX Adding value .v."1"."Totalise"."Password" = "Secret password"
[agent-ini] IniFile.cc(setMyValue):XXX Adding value .v."2"."arcor"."Password" = "Public password"
[agent-ini] IniParser.cc(parse):XXX Rewriting multi/private.in.1.test to 1
[agent-ini] IniParser.cc(parse):XXX Rewriting multi/private.in.2.test to 2
[agent-ini] IniParser.cc(getFileName):XXX Rewriting 1 to multi/private.in.1.test
[agent-ini] IniParser.cc(getFileName):XXX Rewriting 2 to multi/private.in.2.test
[YCP] multi/private.ycp:XXX secret file mode: $["exit":0, "stderr":"", "stdout":"600\n"]
[YCP] multi/private.ycp:XXX public file mode: $["exit":0, "stderr":"", "stdout":"644\n"]
[agent-ini] IniParser.cc(write):XXX File multi/private.in.*.test did not change. Not saving.
10 changes: 10 additions & 0 deletions agent-ini/testsuite/multi/private.in.1
@@ -0,0 +1,10 @@
[Dialer Totalise]
Compuserve = 0
Provider = Totalise
Phone = 08453001470
[End]

[Dialer force9]
Provider = Force9
Phone = 08451424000
[End]
11 changes: 11 additions & 0 deletions agent-ini/testsuite/multi/private.in.2
@@ -0,0 +1,11 @@
[Dialer arcor]
Compuserve = 0
Provider = Arcor
[End]

[Dialer mobilcom]
Compuserve = 0
Provider = Mobilcom
Phone = 0101901929
[End]

25 changes: 25 additions & 0 deletions agent-ini/testsuite/multi/private.out
@@ -0,0 +1,25 @@
(nil)
multi/private.in.1.test -------------------------------
[Dialer Totalise]
Compuserve = 0
Provider = Totalise
Phone = 08453001470
Password = Secret password
[End]

[Dialer force9]
Provider = Force9
Phone = 08451424000
[End]
multi/private.in.2.test -------------------------------
[Dialer arcor]
Compuserve = 0
Provider = Arcor
Password = Public password
[End]

[Dialer mobilcom]
Compuserve = 0
Provider = Mobilcom
Phone = 0101901929
[End]
24 changes: 24 additions & 0 deletions agent-ini/testsuite/multi/private.scr
@@ -0,0 +1,24 @@
.

`ag_ini(
`IniAgent( [ "multi/private.in.*.test" ],
$[
"rewrite" : [
[ "multi/private\.in\.(.)\.test$", "multi/private.in.%s.test"],
],
"subindent" : " ",
"comments": [ "^[ \t]*#.*", "^[ \t]*$" ],
"sections" : [
$[
"begin" : [ "[ \t]*\\[Dialer[ \t]+(.*[^ \t])[ \t]*\\][ \t]*", "[Dialer %s]" ],
"end" : [ "^[ \t]*\\[End\\][ \t]*$", "[End]", ],
],
],
"params" : [
$[
"match" : [ "^[ \t]*([^=]*[^ \t=])[ \t]*=[ \t]*(.*[^ \t]|)[ \t]*$" , "%s = %s"],
],
],
]
)
)
26 changes: 26 additions & 0 deletions agent-ini/testsuite/multi/private.ycp
@@ -0,0 +1,26 @@
//
// Multiple files test
//
// providers.rpm
//


{
SCR::RegisterAgent (.target, `ag_system ());
any out = nil;

SCR::Write (.v."1"."Totalise"."Password", "Secret password");
SCR::Write (.section_private."1", true);

SCR::Write (.v."2"."arcor"."Password", "Public password");

SCR::Write (., nil); //flush

out = SCR::Execute (.target.bash_output, "stat -c %a multi/private.in.1.test");
y2milestone("secret file mode: %1", out);

out = SCR::Execute (.target.bash_output, "stat -c %a multi/private.in.2.test");
y2milestone("public file mode: %1", out);

return nil;
}

0 comments on commit 7fe2e3d

Please sign in to comment.