Hi,
I have code that sets uid after I start it as root. I have a user A
that owns a key, and I su - to root. Then I do:
./simple-signer <my key name> '<data to sign>' A
In this case, gpgme does not find the key for user A.
However, if I run the following as user A:
./simple-signer <my key name> '<data to sign>'
gpgme finds the key for user A.
I am attaching my code, for reference. My question is : do I need to
do something that will enable gpgme to find the key when I run my code
as root?
Thanks,
Kaustubh
--
Kaustubh Gadkari
kaustubh [dot] gadkari [at] gmail [dot] com
#include <stdio.h>
#include <gpgme.h>
#include <gpg-error.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <locale.h>
#include <pwd.h>
#include <stdlib.h>
#include <pwd.h>
#include <string>
using namespace std;
void _usage()
{
fprintf(stdout, "simpl-signer <key ID> <data to sign> [<user name to switch to>]\n");
}
gpgme_error_t bb_cb(void *p_pHook, const char *p_pUidHint, const char *p_pPassphraseInfo, int p_iPrevWasBad, int p_iFd)
{
int iRet = GPG_ERR_CANCELED;
const char *szP = getpass("PP> ");
if (NULL != szP)
{
write(p_iFd, szP, strlen(szP));
write(p_iFd, "\n", 1);
iRet = 0;
}
return iRet;
}
int main(int argc, char *argv[])
{
int iRet = 0;
bool bRet = false;
if (argc < 2)
{
fprintf(stderr, "Unable to run w/o a key name.\n");
_usage();
exit(1);
}
else if (argc < 3)
{
fprintf(stderr, "Unable to sign w/o something to sign.\n");
_usage();
exit(1);
}
string sKey = argv[1];
string sData = argv[2];
string sOutputSig;
if (argc > 3)
{
if (getuid() != 0)
{
fprintf(stderr, "Can't setuid() if not root.\n");
}
else
{
struct passwd *pPass = getpwnam(argv[3]);
if (NULL == pPass)
{
fprintf(stderr, "Can't find user: '%s'\n", argv[3]);
}
else if (setuid(pPass->pw_uid) < 0)
{
fprintf(stderr, "Can't setuid(): '%s'\n", strerror(errno));
}
else
{
fprintf(stdout, "UID is now: %d\n", getuid());
}
}
}
gpgme_ctx_t pGpgmeCtx;
gpgme_engine_info_t pEngInfo = NULL;
const char *szProto = NULL;
gpg_error_t tErr;
const char *szVersion = NULL;
gpgme_key_t tKey;
szVersion = gpgme_check_version(NULL);
setlocale(LC_ALL, "");
gpg_err_init();
gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
if (GPG_ERR_NO_ERROR != (tErr = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP)))
{
fprintf(stderr, "GPG engine doesn't seem to support OpenPGP protocol: '%s'\n", gpg_strerror(tErr));
}
else if (GPG_ERR_NO_ERROR != (tErr = gpgme_new(&pGpgmeCtx)))
{
fprintf(stderr, "Unable to get GPG context: '%s'\n", gpg_strerror(tErr));
}
else if (GPG_ERR_NO_ERROR != (tErr = gpgme_set_protocol(pGpgmeCtx, GPGME_PROTOCOL_OpenPGP)))
{
fprintf(stderr, "Unable to set protocol to OpenPGP: '%s'\n", gpg_strerror(tErr));
}
else if (NULL == (szProto = gpgme_get_protocol_name(GPGME_PROTOCOL_OpenPGP)))
{
fprintf(stderr, "Unable to get protocol name, but protocol exists for OpenPGP?\n");
}
else if (GPG_ERR_NO_ERROR != (tErr = gpgme_get_engine_info(&pEngInfo)))
{
fprintf(stderr, "Unable to get engine info: '%s'\n", gpg_strerror(tErr));
}
else if (GPG_ERR_NO_ERROR != (tErr = gpgme_ctx_set_engine_info(pGpgmeCtx,
GPGME_PROTOCOL_OpenPGP,
pEngInfo->file_name,
pEngInfo->home_dir)))
{
fprintf(stderr, "Unable to set engine info in context: '%s'\n", gpg_strerror(tErr));
}
else if (0 != (tErr = gpgme_get_key(pGpgmeCtx, sKey.c_str(), &tKey, 1))
|| NULL == tKey)
{
fprintf(stderr, "Error while getting key with ID: '%s': [%d] %s\n", sKey.c_str(), tErr, gpgme_strerror(tErr));
}
else if (0 != (tErr = gpgme_signers_add(pGpgmeCtx, tKey)))
{
fprintf(stderr, "Error while adding signor key for ID: '%s': [%d] %s\n", sKey.c_str(), tErr, gpgme_strerror(tErr));
gpgme_key_unref(tKey);
}
else
{
gpgme_set_armor(pGpgmeCtx, 1);
gpgme_set_passphrase_cb(pGpgmeCtx, bb_cb, NULL);
gpgme_key_unref(tKey);
bRet = true;
}
if (bRet)
{
ssize_t lRet = 0;
size_t uDataSize = sData.size();
off_t tCurr = 0;
gpgme_error_t tErr;
gpgme_data_t tData;
gpgme_data_t tSig;
gpgme_sig_mode_t tMode = GPGME_SIG_MODE_DETACH;
if (GPG_ERR_NO_ERROR != (tErr = gpgme_data_new(&tData)))
{
fprintf(stderr, "Unable to create data buffer: '%s'\n", gpgme_strerror(tErr));
bRet = false;
}
else if (GPG_ERR_NO_ERROR != (tErr = gpgme_data_new(&tSig)))
{
fprintf(stderr, "Unable to create signature buffer: '%s'\n", gpgme_strerror(tErr));
gpgme_data_release(tData);
bRet = false;
}
else if (-1 == (lRet = gpgme_data_write(tData, sData.c_str(), uDataSize))
|| uDataSize != (size_t) lRet
|| 0 != (lRet = gpgme_data_seek(tData, 0, SEEK_SET)))
{
fprintf(stderr, "Unable to write data: %d: %s\n", lRet, strerror(errno));
gpgme_data_release(tData);
gpgme_data_release(tSig);
bRet = false;
}
else if (GPG_ERR_NO_ERROR != (tErr = gpgme_op_sign(pGpgmeCtx, tData, tSig, tMode)))
{
fprintf(stderr, "Unable to sign: '%s'\n", gpg_strerror(tErr));
gpgme_data_release(tData);
gpgme_data_release(tSig);
bRet = false;
}
else if ((tCurr = gpgme_data_seek(tSig, 0, SEEK_CUR)) <= 0)
{
fprintf(stderr, "Unable to get sig's current offset: '%s'\n", strerror(errno));
gpgme_data_release(tData);
gpgme_data_release(tSig);
bRet = false;
}
else
{
char *pBuff = new char[tCurr + 1];
memset(pBuff, 0, tCurr + 1);
gpgme_data_seek(tSig, 0, SEEK_SET);
int iErr = gpgme_data_read(tSig, pBuff, tCurr);
if (iErr <= 0)
{
fprintf(stderr, "Unable to read new signature: '%s'\n", strerror(errno));
bRet = false;
}
else
{
sOutputSig = pBuff;
fprintf(stdout, "The sig for: '%s' is '%s'\n", sData.c_str(), sOutputSig.c_str());
bRet = true;
}
gpgme_data_seek(tData, 0, SEEK_SET);
gpgme_data_seek(tSig, 0, SEEK_SET);
gpgme_data_release(tData);
gpgme_data_release(tSig);
delete[] pBuff;
}
}
gpgme_release(pGpgmeCtx);
return iRet;
}
_______________________________________________
Gnupg-users mailing list
[email protected]
http://lists.gnupg.org/mailman/listinfo/gnupg-users