00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <kdebug.h>
00020
00021 #include <config.h>
00022
00023 #include "kpgpbase.h"
00024 #include "kpgp.h"
00025 #include "kpgpblock.h"
00026
00027 #include <stdlib.h>
00028 #include <unistd.h>
00029 #include <sys/poll.h>
00030 #include <sys/types.h>
00031 #include <sys/wait.h>
00032 #include <errno.h>
00033
00034 #include <tqapplication.h>
00035
00036
00037 namespace Kpgp {
00038
00039 Base::Base()
00040 : input(), output(), error(), errMsg(), status(OK)
00041 {
00042 }
00043
00044
00045 Base::~Base()
00046 {
00047 }
00048
00049
00050 void
00051 Base::clear()
00052 {
00053 input = TQCString();
00054 output = TQCString();
00055 error = TQCString();
00056 errMsg = TQString();
00057 status = OK;
00058 }
00059
00060
00061 int
00062 Base::run( const char *cmd, const TQString &passphrase, bool onlyReadFromPGP )
00063 {
00064
00065
00066
00067
00068 char str[1025] = "\0";
00069 int pin[2], pout[2], perr[2], ppass[2];
00070 int len, len2;
00071 FILE *pass;
00072 pid_t child_pid;
00073 int childExiStatus;
00074 struct pollfd pollin, pollout, pollerr;
00075 int pollstatus;
00076
00077 if (!passphrase.isEmpty())
00078 {
00079 if (pipe(ppass) < 0) {
00080
00081
00082 printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
00083 }
00084
00085 pass = fdopen(ppass[1], "w");
00086 TQCString pass2 = passphrase.local8Bit();
00087 fwrite(pass2, sizeof(char), pass2.length(), pass);
00088 fwrite("\n", sizeof(char), 1, pass);
00089 fclose(pass);
00090 close(ppass[1]);
00091
00092
00093 TQCString tmp;
00094 tmp.sprintf("%d",ppass[0]);
00095 ::setenv("PGPPASSFD",tmp.data(),1);
00096
00097
00098
00099
00100 }
00101 else
00102 ::unsetenv("PGPPASSFD");
00103
00104
00105 kdDebug(5100) << "pgp cmd = " << cmd << endl;
00106
00107
00108
00109 error = "";
00110 output = "";
00111
00112 if (pipe(pin) < 0) {
00113
00114
00115 printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
00116 }
00117 if (pipe(pout) < 0) {
00118
00119
00120 printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
00121 }
00122 if (pipe(perr) < 0) {
00123
00124
00125 printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
00126 }
00127
00128 TQApplication::flushX();
00129 if(!(child_pid = fork()))
00130 {
00131
00132 close(pin[1]);
00133 dup2(pin[0], 0);
00134 close(pin[0]);
00135
00136 close(pout[0]);
00137 dup2(pout[1], 1);
00138 close(pout[1]);
00139
00140 close(perr[0]);
00141 dup2(perr[1], 2);
00142 close(perr[1]);
00143
00144 execl("/bin/sh", "sh", "-c", cmd, (void *)0);
00145 _exit(127);
00146 }
00147
00148
00149 close(pin[0]);
00150 close(pout[1]);
00151 close(perr[1]);
00152
00153
00154 pollout.fd = pout[0];
00155 pollout.events = POLLIN;
00156 pollout.revents = 0;
00157 pollerr.fd = perr[0];
00158 pollerr.events = POLLIN;
00159 pollerr.revents = 0;
00160
00161
00162 pollin.fd = pin[1];
00163 pollin.events = POLLOUT;
00164 pollin.revents = 0;
00165
00166 if (!onlyReadFromPGP) {
00167 if (!input.isEmpty()) {
00168
00169 uint input_length = input.length();
00170 for (unsigned int i=0; i<input_length; i+=len2) {
00171 len2 = 0;
00172
00173
00174
00175 pollstatus = poll(&pollin, 1, 5);
00176 if (pollstatus == 1) {
00177
00178 if (pollin.revents & POLLERR) {
00179 kdDebug(5100) << "PGP seems to have hung up" << endl;
00180 break;
00181 }
00182 else if (pollin.revents & POLLOUT) {
00183
00184 if ((len2 = input.find('\n', i)) == -1)
00185 len2 = input_length - i;
00186 else
00187 len2 = len2 - i + 1;
00188
00189
00190 len2 = write(pin[1], input.data() + i, len2);
00191
00192 }
00193 }
00194 else if (!pollstatus) {
00195
00196
00197 }
00198 else if (pollstatus == -1) {
00199 kdDebug(5100) << "Error while polling pin[1]: "
00200 << pollin.revents << endl;
00201 }
00202
00203 if (pout[0] >= 0) {
00204 do {
00205
00206
00207 pollstatus = poll(&pollout, 1, 0);
00208 if (pollstatus == 1) {
00209
00210 if (pollout.revents & POLLIN) {
00211
00212 if ((len = read(pout[0],str,1024))>0) {
00213
00214 str[len] ='\0';
00215 output += str;
00216 }
00217 else
00218 break;
00219 }
00220 }
00221 else if (pollstatus == -1) {
00222 kdDebug(5100) << "Error while polling pout[0]: "
00223 << pollout.revents << endl;
00224 }
00225 } while ((pollstatus == 1) && (pollout.revents & POLLIN));
00226 }
00227
00228 if (perr[0] >= 0) {
00229 do {
00230
00231
00232 pollstatus = poll(&pollerr, 1, 0);
00233 if (pollstatus == 1) {
00234
00235 if (pollerr.revents & POLLIN) {
00236
00237 if ((len = read(perr[0],str,1024))>0) {
00238
00239 str[len] ='\0';
00240 error += str;
00241 }
00242 else
00243 break;
00244 }
00245 }
00246 else if (pollstatus == -1) {
00247 kdDebug(5100) << "Error while polling perr[0]: "
00248 << pollerr.revents << endl;
00249 }
00250 } while ((pollstatus == 1) && (pollerr.revents & POLLIN));
00251 }
00252
00253
00254 if ((pollstatus == 1) &&
00255 ((pollout.revents & POLLHUP) || (pollerr.revents & POLLHUP))) {
00256 kdDebug(5100) << "PGP hung up" << endl;
00257 break;
00258 }
00259 }
00260 }
00261 else {
00262 if (write(pin[1], "\n", 1) < 0) {
00263
00264
00265 printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
00266 }
00267 }
00268
00269 }
00270 close(pin[1]);
00271
00272 pid_t waitpidRetVal;
00273
00274 do {
00275
00276 childExiStatus = 0;
00277 waitpidRetVal = waitpid(child_pid, &childExiStatus, WNOHANG);
00278
00279 if (pout[0] >= 0) {
00280 do {
00281
00282
00283 pollstatus = poll(&pollout, 1, 0);
00284 if (pollstatus == 1) {
00285
00286 if (pollout.revents & POLLIN) {
00287
00288 if ((len = read(pout[0],str,1024))>0) {
00289
00290 str[len] ='\0';
00291 output += str;
00292 } else {
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 pollout.revents |= POLLHUP;
00312 break;
00313 }
00314 }
00315 }
00316 else if (pollstatus == -1) {
00317 kdDebug(5100) << "Error while polling pout[0]: "
00318 << pollout.revents << endl;
00319 }
00320 } while ((pollstatus == 1) && (pollout.revents & POLLIN));
00321 }
00322
00323 if (perr[0] >= 0) {
00324 do {
00325
00326
00327 pollstatus = poll(&pollerr, 1, 0);
00328 if (pollstatus == 1) {
00329
00330 if (pollerr.revents & POLLIN) {
00331
00332 if ((len = read(perr[0],str,1024))>0) {
00333
00334 str[len] ='\0';
00335 error += str;
00336 } else {
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 pollerr.revents |= POLLHUP;
00356 break;
00357 }
00358 }
00359 }
00360 else if (pollstatus == -1) {
00361 kdDebug(5100) << "Error while polling perr[0]: "
00362 << pollerr.revents << endl;
00363 }
00364 } while ((pollstatus == 1) && (pollerr.revents & POLLIN));
00365 }
00366 } while (waitpidRetVal == 0);
00367
00368 close(pout[0]);
00369 close(perr[0]);
00370
00371 unsetenv("PGPPASSFD");
00372 if (!passphrase.isEmpty())
00373 close(ppass[0]);
00374
00375
00376 if (WIFEXITED(childExiStatus) != 0) {
00377
00378 childExiStatus = WEXITSTATUS(childExiStatus);
00379 kdDebug(5100) << "PGP exited with exit status " << childExiStatus
00380 << endl;
00381 }
00382 else {
00383 childExiStatus = -1;
00384 kdDebug(5100) << "PGP exited abnormally!" << endl;
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394 kdDebug(5100) << error << endl;
00395
00396 return childExiStatus;
00397 }
00398
00399
00400 int
00401 Base::runGpg( const char *cmd, const TQString &passphrase, bool onlyReadFromGnuPG )
00402 {
00403
00404
00405
00406
00407 char str[1025] = "\0";
00408 int pin[2], pout[2], perr[2], ppass[2];
00409 int len, len2;
00410 FILE *pass;
00411 pid_t child_pid;
00412 int childExiStatus;
00413 char gpgcmd[1024] = "\0";
00414 struct pollfd poller[3];
00415 int num_pollers = 0;
00416 const int STD_OUT = 0;
00417 const int STD_ERR = 1;
00418 const int STD_IN = 2;
00419 int pollstatus;
00420
00421 if (!passphrase.isEmpty())
00422 {
00423 if (pipe(ppass) < 0) {
00424
00425
00426 printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
00427 }
00428
00429 pass = fdopen(ppass[1], "w");
00430 TQCString pass2 = passphrase.local8Bit();
00431 fwrite(pass2, sizeof(char), pass2.length(), pass);
00432 fwrite("\n", sizeof(char), 1, pass);
00433 fclose(pass);
00434 close(ppass[1]);
00435
00436
00437
00438 }
00439
00440
00441
00442
00443
00444
00445 error = "";
00446 output = "";
00447
00448 if (pipe(pin) < 0) {
00449
00450
00451 printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
00452 }
00453 if (pipe(pout) < 0) {
00454
00455
00456 printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
00457 }
00458 if (pipe(perr) < 0) {
00459
00460
00461 printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
00462 }
00463
00464 if (!passphrase.isEmpty()) {
00465 if( mVersion >= "1.0.7" ) {
00466
00467 if( 0 == getenv("GPG_AGENT_INFO") ) {
00468
00469 snprintf( gpgcmd, 1023,
00470 "LANGUAGE=C gpg --no-use-agent --passphrase-fd %d %s",
00471 ppass[0], cmd );
00472 }
00473 else {
00474
00475 snprintf( gpgcmd, 1023,
00476 "LANGUAGE=C gpg --use-agent %s",
00477 cmd );
00478 }
00479 }
00480 else {
00481
00482 snprintf( gpgcmd, 1023,
00483 "LANGUAGE=C gpg --passphrase-fd %d %s",
00484 ppass[0], cmd );
00485 }
00486 }
00487 else {
00488 snprintf(gpgcmd, 1023, "LANGUAGE=C gpg %s",cmd);
00489 }
00490
00491 TQApplication::flushX();
00492 if(!(child_pid = fork()))
00493 {
00494
00495 close(pin[1]);
00496 dup2(pin[0], 0);
00497 close(pin[0]);
00498
00499 close(pout[0]);
00500 dup2(pout[1], 1);
00501 close(pout[1]);
00502
00503 close(perr[0]);
00504 dup2(perr[1], 2);
00505 close(perr[1]);
00506
00507
00508
00509 if (!passphrase.isEmpty()) {
00510 if( mVersion >= "1.0.7" ) {
00511
00512 if( 0 == getenv("GPG_AGENT_INFO") ) {
00513
00514 snprintf( gpgcmd, 1023,
00515 "LANGUAGE=C gpg --no-use-agent --passphrase-fd %d %s",
00516 ppass[0], cmd );
00517 }
00518 else {
00519
00520 snprintf( gpgcmd, 1023,
00521 "LANGUAGE=C gpg --use-agent %s",
00522 cmd );
00523 }
00524 }
00525 else {
00526
00527 snprintf( gpgcmd, 1023,
00528 "LANGUAGE=C gpg --passphrase-fd %d %s",
00529 ppass[0], cmd );
00530 }
00531 }
00532 else {
00533 snprintf(gpgcmd, 1023, "LANGUAGE=C gpg %s",cmd);
00534 }
00535
00536 kdDebug(5100) << "pgp cmd = " << gpgcmd << endl;
00537
00538 execl("/bin/sh", "sh", "-c", gpgcmd, (void *)0);
00539 _exit(127);
00540 }
00541
00542
00543
00544 close(pin[0]);
00545 close(pout[1]);
00546 close(perr[1]);
00547
00548
00549 poller[STD_OUT].fd = pout[0];
00550 poller[STD_OUT].events = POLLIN;
00551 poller[STD_ERR].fd = perr[0];
00552 poller[STD_ERR].events = POLLIN;
00553 num_pollers = 2;
00554
00555 if (!onlyReadFromGnuPG) {
00556
00557 poller[STD_IN].fd = pin[1];
00558 poller[STD_IN].events = POLLOUT;
00559 num_pollers = 3;
00560 } else {
00561 close (pin[1]);
00562 pin[1] = -1;
00563 }
00564
00565 pid_t waitpidRetVal;
00566 unsigned int input_pos = 0;
00567 uint input_length = input.length();
00568
00569 do {
00570
00571 childExiStatus = 0;
00572 waitpidRetVal = waitpid(child_pid, &childExiStatus, WNOHANG);
00573
00574 do {
00575
00576 pollstatus = poll(poller, num_pollers, 10);
00577 if( 0 < pollstatus ) {
00578
00579 if (poller[STD_OUT].revents & POLLIN) {
00580
00581 if ((len = read(pout[0],str,1024))>0) {
00582
00583 str[len] ='\0';
00584 output += str;
00585 }
00586 else {
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 poller[STD_OUT].revents |= POLLHUP;
00605 poller[STD_OUT].events = 0;
00606 }
00607 } else if (poller[STD_OUT].revents & POLLHUP) {
00608
00609 poller[STD_OUT].events = 0;
00610 }
00611
00612
00613 if (poller[STD_ERR].revents & POLLIN) {
00614
00615 if ((len = read(poller[STD_ERR].fd,str,1024))>0) {
00616
00617 str[len] ='\0';
00618 error += str;
00619 }
00620 else {
00621
00622 poller[STD_ERR].revents |= POLLHUP;
00623 poller[STD_ERR].events = 0;
00624 }
00625 } else if (poller[STD_ERR].revents & POLLHUP) {
00626
00627 poller[STD_ERR].events = 0;
00628 }
00629
00630 if (num_pollers > 2) {
00631 if (poller[STD_IN].revents & ( POLLERR | POLLHUP ) ) {
00632 kdDebug(5100) << "GnuPG seems to have hung up" << endl;
00633 close (pin[1]);
00634 pin[1] = -1;
00635 --num_pollers;
00636 }
00637 else if (poller[STD_IN].revents & POLLOUT) {
00638 if (!input.isEmpty()) {
00639
00640 if ((len2 = input.find('\n', input_pos)) == -1)
00641 len2 = input_length - input_pos;
00642 else
00643 len2 = len2 - input_pos + 1;
00644
00645
00646 len2 = write(pin[1], input.data() + input_pos, len2 );
00647
00648 input_pos += len2;
00649
00650
00651 if (input_pos >= input_length) {
00652
00653 close (pin[1]);
00654 pin[1] = -1;
00655 --num_pollers;
00656 }
00657 }
00658 else {
00659 if (write(pin[1], "\n", 1) < 0) {
00660
00661
00662 printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
00663 }
00664
00665 close (pin[1]);
00666 pin[1] = -1;
00667 --num_pollers;
00668 }
00669 }
00670 }
00671 }
00672 } while ( (pollstatus > 0) && ( (num_pollers > 2)
00673 || (poller[STD_OUT].events != 0)
00674 || (poller[STD_ERR].events != 0) ) );
00675
00676 if (pollstatus == -1) {
00677 kdDebug(5100) << "GnuPG poll failed, errno: " << errno << endl;
00678 }
00679
00680 } while(waitpidRetVal == 0);
00681
00682 if( 0 <= pin[1] )
00683 close (pin[1]);
00684 close(pout[0]);
00685 close(perr[0]);
00686
00687 if (!passphrase.isEmpty())
00688 close(ppass[0]);
00689
00690
00691 if (WIFEXITED(childExiStatus) != 0) {
00692
00693 childExiStatus = WEXITSTATUS(childExiStatus);
00694 kdDebug(5100) << "GnuPG exited with exit status " << childExiStatus
00695 << endl;
00696 }
00697 else {
00698 childExiStatus = -1;
00699 kdDebug(5100) << "GnuPG exited abnormally!" << endl;
00700 }
00701
00702
00703
00704
00705
00706
00707 kdDebug(5100) << "gpg stderr:\n" << error << endl;
00708
00709 return childExiStatus;
00710 }
00711
00712
00713 TQCString
00714 Base::addUserId()
00715 {
00716 TQCString cmd;
00717 TQCString pgpUser = Module::getKpgp()->user();
00718
00719 if(!pgpUser.isEmpty())
00720 {
00721 cmd += " -u 0x";
00722 cmd += pgpUser;
00723 return cmd;
00724 }
00725 return TQCString();
00726 }
00727
00728
00729 }