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