Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Scripting Input

2 views
Skip to first unread message

Terry E. Rataiczak, Sr.

unread,
Jun 27, 2000, 3:00:00 AM6/27/00
to
I want to write a /bin/sh script that takes and argument and completes the
passwd username command. Does anyone know how to go about this? I have the
script taking the arguments and calling passwd, but it just waits for me to
enter a password. Thanks in Advance.

Thanks!

Jehsom

unread,
Jun 27, 2000, 3:00:00 AM6/27/00
to

See the recent comp.unix.shell thread "Change password in a script."

Moshe

--
jehsom@ angband.org bellsouth.net burdell.org cc.gatech.edu polter.net
nullity.dhs.org resnet.gatech.edu wreck.org yo.dhs.org usa.net; moshe@
medmanager.com; gte741e mj116 @prism.gatech.edu; jacobsonconsulting@
usa.net; moshe@ medmanager.com; ICQ 1900670; Post tech Qs to the NG pls

Joe Durusau

unread,
Jun 27, 2000, 3:00:00 AM6/27/00
to
You can't do that in most systems without magnificent trouble,
and hig risk to system integrity. The freeware program expect will
let you do it, but you have a massive security hole because of the
file with cleartext passwords in it. You could try something with
ctypt and editing of the passwd (and shadow) files, but I don't
reccommend it.

Speaing only for myself,

Joe Durusau


"Terry E. Rataiczak, Sr." wrote:
>
> I want to write a /bin/sh script that takes and argument and completes the
> passwd username command. Does anyone know how to go about this? I have the
> script taking the arguments and calling passwd, but it just waits for me to
> enter a password. Thanks in Advance.
>

> Thanks!

Matt Lesko

unread,
Jun 27, 2000, 3:00:00 AM6/27/00
to
I think that you want to use 'expect' here, as you are trying to run the command
interactively. Expect is a scripting language that allows scripts to act with
interactive commands, try to find a tutorial on the web somewhere, I know there
must be one. Of course, in the expect script, you'll have the same security
problem as this shell script: if someone can read it, they'll know the password.
Writing a wrapper in C and compiling it (i.e., using syscall() in the program)
might make this a little harder, but someone could use the 'strings' command on
the executable to get out the password. Maybe some hashing or rotating in the C
program would solve that. Could also try (since I'm assuming you're running this
command as root, or at least SUID root) simply changing the hashed password in
/etc/passwd or /etc/shadow. Use crypt once, and then use that value to overwrite
the previous password field. Correct me if I'm wrong, but with crypt, the same
password should result in the same encrypted version. Or if this is just a
situation where near-paranoia security isn't an issue, just go with my first
suggestion: expect.

-- Matt Lesko
matt.advancedatatools@com
[ if you can't figure out how to get the real address, don't bother ]

"The religions of the future will resemble science fiction." -- Dr. Timothy
Leary

pe...@icke-reklam.ipsec.nu

unread,
Jun 30, 2000, 3:00:00 AM6/30/00
to
In comp.unix.admin Terry E. Rataiczak, Sr. <trata...@stratuswave.com> wrote:
> I want to write a /bin/sh script that takes and argument and completes the
> passwd username command. Does anyone know how to go about this? I have the
> script taking the arguments and calling passwd, but it just waits for me to
> enter a password. Thanks in Advance.

the utility 'passwd' explicitly opens /dev/tty for reading. That's done
for security reasons.

If you don't have source to 'passwd' you have to work around , one
way might be "expect" (look at learest pd-archive). I also remember
this done in perl but i don't remember where ---

> Thanks!

--
Peter Håkanson
IPSec Sverige (At the Riverside of Gothenburg, home of Volvo)
Sorry about my e-mail address, but i'm trying to keep spam out.
Remove "icke-reklam" and it works.

Carlos Duarte

unread,
Jul 3, 2000, 3:00:00 AM7/3/00
to
In comp.unix.admin Terry E. Rataiczak, Sr. <trata...@stratuswave.com> wrote:

> I want to write a /bin/sh script that takes and argument and completes the
> passwd username command. Does anyone know how to go about this? I have the
> script taking the arguments and calling passwd, but it just waits for me to
> enter a password. Thanks in Advance.

passwd needs a terminal to read from.
do a:
mkfifo z

then write/read to z the same you would do interactively:

passwd cgd < z &
read < z
echo cgdcgd > z
read < z
echo cgdcgd > z

hint: probably this would not work as is-- this is best
done in C, with a select looping on z, for read/write
data when it can... this way (as is) it might block
on a write, and (most probably) on a read


--
PORTUGAL ROBBED AT EURO2000: http://cgd.teleweb.pt

Nate Eldredge

unread,
Jul 3, 2000, 3:00:00 AM7/3/00
to
Carlos Duarte <c...@teleweb.pt> writes:

This won't work at all, since a FIFO is not a terminal. Anyway,
`passwd' doesn't care what its standard input and output are, it opens
/dev/tty and talks to the user there. To intercept this, you'll need
to use something like `expect', which emulates a terminal.

--

Nate Eldredge
neld...@hmc.edu

cLIeNUX user

unread,
Jul 4, 2000, 3:00:00 AM7/4/00
to
neld...@hmc.edu...

As a curiosity thing, is expect-like behavior impossible from a Bourne
or POSIX shell? Another one that has stymied me is trying to write
a rudimentry pager in a sh script. Comments?

Rick Hohensee
ri...@clienux.com

Ken Pizzini

unread,
Jul 4, 2000, 3:00:00 AM7/4/00
to
On 4 Jul 2000 03:44:42 GMT, cLIeNUX user <r@your_host.com> wrote:
>As a curiosity thing, is expect-like behavior impossible from a Bourne
>or POSIX shell?

To get expect-like behaviour, you need to interpose a pseudo-tty
between the controlling program and the program which insists on
talking to a tty. Shells do not give you the access you need to
the ioctl() calls which control ptys, and so you need the help
of some other program, such as:
expect
perl
pty
ssh
rsh
telnet

> Another one that has stymied me is trying to write
>a rudimentry pager in a sh script. Comments?

input_file=$1
pagelen=24
cur=1
while read line; do
cur=`expr $cur + 1`
if [ $cur -ge $pagelen ]; then
printf "Press return to continue..."
read junk </dev/tty
fi
printf "%s\n" "$line"
done < "$input_file"

--Ken Pizzini

Carlos Duarte

unread,
Jul 4, 2000, 3:00:00 AM7/4/00
to
[...]

>>This won't work at all, since a FIFO is not a terminal. Anyway,
>>`passwd' doesn't care what its standard input and output are, it opens
>>/dev/tty and talks to the user there. To intercept this, you'll need
>>to use something like `expect', which emulates a terminal.

this works if passwd behaves like the linux passwd, else is just
a matter of polling a bit the WAITs.
it is called as
do_chg_pass(user, newpass);
and must be run by root

.......

#define PASSWD "/usr/bin/passwd"

static int
openpty(int *amaster, int *aslave)
{
static char line[] = "/dev/ptyXX";
register const char *cp1, *cp2;
register int master, slave;

for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
line[8] = *cp1;
for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
line[5] = 'p';
line[9] = *cp2;
if ((master = open(line, O_RDWR, 0)) == -1) {
if (errno == ENOENT)
return (-1); /* out of ptys */
} else {
line[5] = 't';
if ((slave = open(line, O_RDWR, 0)) != -1) {
*amaster = master;
*aslave = slave;
return (0);
}
(void) close(master);
}
}
}
errno = ENOENT; /* out of ptys */
return (-1);
}

static int
do_chg_pass(char *user, char *pass)
{
int master, slave;
fd_set rfds;
struct timeval tv;
char c;
int status;

if (openpty(&master, &slave) == -1) {
/* perror("openpty"); */
return 3;
}
switch (fork()) {
case -1:
/* perror("fork"); */
return 3;
case 0:
/*
* child
*/
(void) close(master);
dup2(slave, 0);
dup2(slave, 1);
dup2(slave, 2);
close(slave);
setuid(0);
execl(PASSWD, "passwd", user, (char *)0);
return (0);
}

/*
* parent
*/
(void) close(slave);

#define WAIT(usecs) \
tv.tv_sec = 0; \
tv.tv_usec = usecs; \
FD_ZERO(&rfds); \
FD_SET(master, &rfds); \
while (select(master+1, &rfds, 0, 0, &tv)>0 && read(master, &c, 1)>0) {\
tv.tv_sec = 1; \
tv.tv_usec = 0; \
FD_ZERO(&rfds); \
FD_SET(master, &rfds); \
}

WAIT(500000);
write(master, pass, strlen(pass));
c = '\n';
write(master, &c, 1);
WAIT(500000);
write(master, pass, strlen(pass));
c = '\n';
write(master, &c, 1);
WAIT(500000);
return 0;

wait(&status);
if (WIFEXITED(status)) {
return 0;
}
return 3;

cLIeNUX user

unread,
Jul 4, 2000, 3:00:00 AM7/4/00
to
k...@halcyon.com...

|||APPLAUSE|||


I hadn't seen the done < "$input_file" before. I have been using
"while read" on stdin lately though. Hmmmmm, that might allow input
on other fd's too.....

Rick Hohensee
ri...@cLIeNUX.com

> --Ken Pizzini

Ken Pizzini

unread,
Jul 4, 2000, 3:00:00 AM7/4/00
to
On 4 Jul 2000 03:43:02 GMT, Ken Pizzini <k...@halcyon.com> wrote:
>input_file=$1
>pagelen=24
>cur=1
>while read line; do
> cur=`expr $cur + 1`
> if [ $cur -ge $pagelen ]; then
> printf "Press return to continue..."
> read junk </dev/tty

I forgot a crucial line here:
cur=1

> fi
> printf "%s\n" "$line"
>done < "$input_file"

--Ken Pizzini

0 new messages