old-www/LDP/LG/issue85/okopnik.html

203 lines
10 KiB
HTML

<!--startcut ==============================================-->
<!-- *** BEGIN HTML header *** -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML><HEAD>
<title>Perl One-Liner of the Month: The Case of the Duplicate UIDs LG #85</title>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
ALINK="#FF0000">
<!-- *** END HTML header *** -->
<!-- *** BEGIN navbar *** -->
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="nielsen.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue85/okopnik.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../lg_faq.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="foolish.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
<!-- *** END navbar *** -->
<!--endcut ============================================================-->
<TABLE BORDER><TR><TD WIDTH="200">
<A HREF="http://www.linuxgazette.com/">
<IMG ALT="LINUX GAZETTE" SRC="../gx/2002/lglogo_200x41.png"
WIDTH="200" HEIGHT="41" border="0"></A>
<BR CLEAR="all">
<SMALL>...<I>making Linux just a little more fun!</I></SMALL>
</TD><TD WIDTH="380">
<CENTER>
<BIG><BIG><STRONG><FONT COLOR="maroon">Perl One-Liner of the Month: The Case of the Duplicate UIDs</FONT></STRONG></BIG></BIG>
<BR>
<STRONG>By <A HREF="../authors/okopnik.html">Ben Okopnik</A></STRONG>
</CENTER>
</TD></TR>
</TABLE>
<P>
<!-- END header -->
<H3>Chapter 1</H3>
<p>The e-mail was short, succinct, and got right to the point.
<BLOCKQUOTE><PRE>
Woomert -
I'll be short, succinct, and get right to the point.
Three-company merger.
Nervous sysadmin.
3000+ users.
/etc/passwd.
UIDs.
Regards,
Frink Ooblick
</PRE></BLOCKQUOTE>
<p>Woomert Foonly, the Hard-Nosed Computer Detective, chuckled to himself.
The client had been rather loud and incoherent on the phone, with "It doesn't
work!" and "I need help!" being the chief features of his conversation.
Woomert had sent Frink to the site to reconnoiter, and the above was the
highly satisfactory result. All that remained was to come up with the solution;
given that only a few short hours remained before the client shut down
for the day, Woomert decided to use his time productively. Let's see -
where was his favorite pillow?...
<H3>Chapter 2</H3>
<p>Refreshed and ready, Woomert appeared at the site, and immediately encountered
a rather excited Frink.
<p>&nbsp;- "Woomert, it's terrible! The file is far too long to search
manually, and the UIDs are all over the map. The sysadmin is contrite,
frantic, and panicked by turns, and his hair is almost all gone. What can
we do?"
<p>&nbsp;- "No worries, mate... oh, sorry. I was just in Canberra a few
hours ago, and some of the influence is still with me. I can tell you from
horrible experience that tomorrow will be even worse: I've got to be in
Dallas in the morning, New York in the afternoon, and Tel Aviv in the evening.
I would advise you to wear earplugs, or absent yourself from my environs
until the accents fade. Ah, the perils of travel..."
<p>Frink was becoming visibly upset.
<p>&nbsp;- "Woomert - you're not taking this seriously. Can't you see that
this is a major problem?"
<p>&nbsp;- "Oh, this? Relax, take it easy. It's not nearly as bad as it
looks, Frink; in fact..."
<p>Woomert deftly extracted his favorite typing gloves from his pocket
and slipped them on.
<p>&nbsp;- "...Perl makes it rather trivial. What we'll do is give the
sysadmin a couple of command-line tools that he can use to resolve this
problem, and - since he's using 'bash' - he'll be able to pull them up
with the 'up-arrow' key as he needs them. Here we go!"
<pre>
<hr width="100%">perl -F: -walne'$h{$F[2]}.="$F[0] ";END{$h{$_}=~/ ./&amp;&amp;print"$_: $h{$_}"for keys%h}' /etc/passwd
<hr
width="100%"></pre>
A list of duplicate UIDs, along with their related usernames scrolled down
the screen after Woomert pressed the "Enter"&nbsp;key. Both Woomert and
Frink noted with interest that there was a <b>triple</b> entry for UID0
-
<p><tt>0: root sashroot kill3r</tt>
<p>&nbsp;- "Well, well. Looks like somebody managed to break in and give
themselves a UID0 (root) account. 'sashroot'&nbsp;is OK - that's the 'standalone
shell'&nbsp;for those rough repair jobs - but 'kill3r'? Well, we'll let
the client know; meanwhile, on with the current problem. The sysadmin will
now have a list of all the duplicates - there don't seem to be all that
many - but searching for the next available UID&nbsp;could be a pain. So,
here's a second tool -"
<pre>
<hr width="100%">perl -wle'{getpwuid++$n&amp;&amp;redo;print$n}'
<hr
width="100%"></pre>
&nbsp;- "That should give him a good start on getting it all straightened
out. As for us - we're homeward bound!"
<H3>Chapter 3</H3>
<p>When they had returned to Woomert's house and were seated in front of
the fireplace - the night had been a cold one, and the wind whistled outside
the window - Frink looked expectantly at Woomert. Noting the look, Woomert
laughed.
<p>&nbsp;- "I know, I know. I should explain, shouldn't I? The air of mystery
is a sharp, pleasant thing, but it is as nothing compared to the pleasure
of learning. Here, let's start with the first one:
<pre>
<hr width="100%">perl -F: -walne'$h{$F[2]}.="$F[0] ";END{$h{$_}=~/ ./&amp;&amp;print"$_: $h{$_}"for keys%h}' /etc/passwd
<hr
width="100%"></pre>
"First, take a look at the command-line switches I used:"
<PRE>
-w Enable warnings
-a Autosplit (see "-F")
-l Enable line-end processing
-n Implicit non-printing loop
-e Execute the following commands
-F:&nbsp;&nbsp;&nbsp; Use ':' as the separator for the '-a' autosplit
</pre>
"If you remember our <a href="../issue84/okopnik.html">last
adventure</a>, all of the above except '-a' and '-F' are already familiar
to you. Autosplitting splits the lines read in by '-n' or '-p', using whitespace
as a default separator and saving the result in the '@F' array. '-F' optionally
redefines the separator by which to split."
<p>"Since we're reading in '/etc/passwd', let's look at the format of the
individual lines in it:"
<pre>borg:x:1026:127:All your base are belong to us!:/home/borg:/bin/bash</pre>
"There are seven standard fields, laid out as 'name - passwd - UID - GID
- GECOS - dir - shell'. The only things we're interested in for the moment
are name and UID; what I'm going to do is build a hash - a very important
data structure in Perl, one of the three basic ones - that contains the
UID (3rd field)&nbsp;as the <b>key</b>, and the name (1st field), followed
by a space, as the <b>value</b>, for all the entries in '/etc/passwd':
<pre>$h{$F[2]}.="$F[0] "</pre>
Since usernames can't have spaces in them, it makes a convenient separator.
Once that's done, I'll loop over the hash and print out any value which
contains a space followed by any character:"
<br>&nbsp;
<pre>$h{$_}=~/ ./&amp;&amp;print"$_: $h{$_}"for keys%h}</pre>
"I see you still look puzzled. Here, let me write out the above in a more
readable form:"
<p><tt>for (&nbsp;keys %h ){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
#&nbsp;Loop over the "%h"&nbsp;hash</tt>
<br><tt>&nbsp;&nbsp;&nbsp; if (&nbsp;$h{$_} =~ / ./ ){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
# Does the value contain a space followed by anything?</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print "$_: $h{$_}\n";&nbsp;&nbsp;
#&nbsp;If so, print the UID, a colon, a space, and the value</tt>
<br><tt>&nbsp;&nbsp;&nbsp; }</tt>
<br><tt>}</tt>
<p>"If you think about it, you'll see that the only thing that will match
the above regex is a value with more than one name in it - meaning a duplicate
UID."
<p>&nbsp;- "All right - now I&nbsp;can see how you got the results. What
about the second expression, the 'next available UID'&nbsp;tool?"
<p>&nbsp;- "Ah, you mean this one:"
<p>
<hr width="100%"><tt>perl -wle'{getpwuid++$n&amp;&amp;redo;print$n}'</tt>
<br>
<hr
width="100%">
<p>"It's nothing but a short loop in which I&nbsp;check if the UID specified
by '$n' exists. If that test succeeds - meaning that there <b>is</b> a
UID equal to '$n' in use - 'redo' gets invoked, '$n' is incremented, and
the test happens again. If it fails, however, '$n' is printed to STDOUT
and the program exits. Useful, and not too complicated. Just a bit of work,
and they should have it all done. The security breach is something else,
but at least now they know about it..."
<!-- *** BEGIN copyright *** -->
<hr>
<CENTER><SMALL><STRONG>
Copyright &copy; 2002, Ben Okopnik.
Copying license <A HREF="../copying.html">http://www.linuxgazette.com/copying.html</A><BR>
Published in Issue 85 of <i>Linux Gazette</i>, December 2002
</STRONG></SMALL></CENTER>
<!-- *** END copyright *** -->
<HR>
<!--startcut ==========================================================-->
<CENTER>
<!-- *** BEGIN navbar *** -->
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="nielsen.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue85/okopnik.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../lg_faq.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="foolish.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
<!-- *** END navbar *** -->
</CENTER>
</BODY></HTML>
<!--endcut ============================================================-->