OK, I've come up with a solution!!! As I mentioned before, kcheckpass is passed the args "-m -S 14" on the command line. I downloaded the kde-workspace-4.11.22 sources for 14.2 and examined kcheckpass.c to see what it does with this file descriptor. It turns out that whatever program launches it (presumably kscreenlocker_greet) first expects to receive some info on fd 14 before it will cough up the password entered by the user. What it expects is a binary '2' followed by a binary '0'. Here's why (if you care).
kcheckpass calls Authenticate((method, login, *(*conv) (ConvRequest, const char *)). Depending on how kcheckpass.c is compiled/linked, that function will be in checkpass_etcpasswd.c, checkpass_pam.c, checkpass_shadow.c and a couple of others.
Using the non-PAM checkpass_etcpasswd.c as an example, Authenticate() in that program will call kcheckpass.c:conv_server (ConvRequest what, const char *prompt) ... where ConvRequest (type of request) = ConvGetHidden = 2, and prompt is passed as zero value (i.e. no prompt).
conv_server() will write the ConvRequest (int 2) as binary int to the specified file descriptor, followed by the binary int length of the prompt (zero). In other words, it writes an int 2 followed by an int 0 to the file descriptor (which always happens to be 14 in my testing).
conv_server() will then read from the file descriptor the binary length of the password string, then it will read the string value itself. The real kcheckpass continues to perform the validation.
Here's my bash replacement for kcheckpass (I've renamed the real one to kcheckpass.kde):
Code:
#!/bin/bash
# Determine if the user is a domain user or local user
x=`wbinfo -u | grep $USER`
# If a local user, run the standard kcheckpass
if [ -z "$x" ]
then
`dirname $0`/kcheckpass.kde $*
rc=$?
exit $rc
fi
# get the file descriptor for retrieving the password
# This will be a command line argument "-S <fd>"
while [ 1 == 1 ]
do
if [ -z "$1" ] # no more args, bad!
then
exit 4
fi
x=`echo $1 | cut -c1-2`
if [ "$x" = "-S" ] # found the file descriptor parameter
then
fd="$2"
break
fi
shift
done
# Now, get password entered by user
passwd=`$(dirname $0)/getkcheckPW $fd`
# Authenticate
ntlm_auth --username="$USER" --password="$passwd"
rc=$?
exit $rc
That script should be fairly self-explanatory. The only real wrinkle is that binary data is exchanged on the file descriptor which is a bit tricky in a shell script. I tried `echo 2000000000000000 | xxd -r -p >&14` and had limited success. Perhaps some shell guru out there can do better?
In the meantime, I did it rather simply in C.
getkcheckPW.c:
Code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
main(int argc, char *argv[])
{
int fd; /* file descriptor */
int convGetHidden = 2; /* code give to (presumably) kscreenlocker_greet for type of Request */
int cnt;
int l; /* length of password */
char passwd[80]; /* buffer to hold returned password */
if (argc < 2) exit(-1); /* expecting file descriptor as arg */
fd = atoi(argv[1]);
write(fd, &convGetHidden, sizeof(convGetHidden)); /* conv_server type of Request */
/* kcheckpass.c sends a prompt of zero length for convGetHidden */
cnt = 0;
write(fd, &cnt, sizeof(cnt));
cnt = read(fd, &l, sizeof(l)); /* Get length of entered password */
cnt = read(fd, passwd, l); /* Get password */
printf("%s\n", passwd);
exit(0);
}
This solution lets me change out the one kcheckpass command without having to rebuild KDE for PAM; which lets me keep slackpkg blacklisting to a minimum. Of course, it could be convincingly argued that this scrpt and C program are possibly MORE complex that rebuilding KDE! For now, I'll continue testing this solution and play around with KDE rebuilding later.
Ivandi, if you've got some ideas on my possible foreground/background issue so I can see the lightdm login screen, I'd much rather go that route and have change basically nothing.