Question compiling PAM module (C++ code)
I wrote an authentication PAM module in C++, as I didn't want to deal with C for a few reasons, so I would prefer not having to re-write the entire module if possible.
I can compile the C++ code just fine, and have no issues running the ld command, but when I try to test the module using pamtester, I get an error message saying: [quote]pamtester: Module is unknown[/code] I dug into /var/log/auth.log (as faillog has no information), and found these entries: Code:
Nov 5 01:22:41 localhost pamtester: PAM unable to dlopen(/lib/security/pam_zorpher.so): /lib/security/pam_zorpher.so Code:
g++ -fPIC -fno-stack-protector -c client.cpp Socket.cpp ClientSocket.cpp random.cpp vc.cpp Code:
Nov 5 01:35:03 localhost pamtester: PAM unable to dlopen(/lib/security/pam_zorpher.so): /lib/security/pam_zorpher.so: undefined symbol: _ZTVN10__cxxabiv117__class_type_infoE |
I think eventually you will have to rewrite it in C.
|
I would start by using the ldd command to see what your .so file depends on.
I have no idea what rules and limits apply to PAM modules. But I doubt NevemTeve's answer (that you must code it in C) is correct. Whatever call points your .so exports should be declared extern "C" otherwise, a client expecting a C .so can't use your C++ .so. But that doesn't require you to rewrite in C. A C++ function declared extern "C" is still a C++ function, it is just called using C calling and naming standards. This (extern C) is probably the important part of the answer, but I don't know enough about PAM modules to give you specifics. It is possible you will need to link some C++ library code from .a files rather than .so files. I really don't know enough about PAM modules to give you any details about that. |
Basically, a C++ program can use a subrutin/plugin written in C, but it is not possible the other way around.
|
Well, I find this weird. I did the extern "C" option, and its not giving me any errors, and here's the revised command line I'm using to compile:
Code:
g++ -fPIC -shared -lpam client.cpp Socket.cpp ClientSocket.cpp vc.cpp -o pam_zorpher.so Quote:
Update I typed up all the above before trying something else. It seemed I forgot to include a specific C++ source file along with the compiler line, which was because I didn't know that file was needed. The module loads fine now, and am able to test it. Thanks everyone for the help, and it seems that the extern "C" was a big help on this as well! |
Please remember mention in your documentation that using your PAM module will break early userspace for systems where /usr is a separate mount point, and that it may break PAM-aware native C programs.
This is because your PAM module, unlike normal PAM modules, has a dependency on /usr/lib/libstdc++. Not only is it only available after /usr has been mounted, but it is known to (occasionally) have symbol collisions with perfectly valid C programs. Weird crashes may occur in innocent C programs using PAM, thanks to your PAM module. Normal PAM modules only depend on libraries under /lib or /lib64 which are part of the root mount, and therefore available to early userspace. They have also minimal dependencies. Certain modules, like pam_ldap (and similar), do have dependencies outside /lib, but that is generally acceptable because the modules will never work before /usr has been mounted and network connections are available anyway. Password checking modules also often depend on external libraries, but they are obviously not critical during early userspace. I also wonder what idiot has installed libgcc_s.so.1 under /usr/lib in your system, and not /lib or /lib64 where it belongs. Having it under /usr (or anywhere other than the root partition) will mean programs relying on it will not work during early userspace. Perhaps your distribution requires /usr to be a part of the root mount, and will fail if it is a separate mount point? (Funny but sad, if so.) The early userspace I refer to here means the time during which init scripts are being run, but /usr has not been mounted yet. It is not that rare to for example mount /usr over the network. In fact, it is a very efficient solution if you have a lot of identical lightweight workstations (almost thin clients), good network infrastructure (GbE or better), and a powerful file server. (On many storage devices, I/O to small files is often slow unless already cached. Two thirds of files in my /usr/lib, /usr/bin, and /usr/sbin are under 16384 bytes. This means that /usr over NFS, with a good NFS server, is surprisingly snappy over GbE.) For the above reasons, I think it is utterly inconsiderate (and, to be honest, stupid) to write a PAM library in C++. There is about zero chance of having it included in any major distribution. C++ is simply not a suitable language for PAM modules. I apologise if my tone sounds harsh. It is just that there are repercussions to the choice of language (or, to be more specific, the library dependencies), which in the case of PAM modules are both complex and dangerous. In my opinion, certainly serious enough to override any personal preferences. |
All times are GMT -5. The time now is 01:38 PM. |