~ubuntu-branches/ubuntu/wily/suphp/wily

« back to all changes in this revision

Viewing changes to src/apache2/mod_suphp.c

  • Committer: Package Import Robot
  • Author(s): Dmitry Shachnev
  • Date: 2014-01-22 16:02:45 UTC
  • mfrom: (1.1.7)
  • Revision ID: package-import@ubuntu.com-20140122160245-x8lirwuql34q0j71
Tags: 0.7.2-0ubuntu1
* New upstream security release.
* Refresh debian/patches/01_debian.diff.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
    suPHP - (c)2002-2005 Sebastian Marsching <sebastian@marsching.com>
3
 
    
 
3
 
4
4
    This file is part of suPHP.
5
5
 
6
6
    suPHP is free software; you can redistribute it and/or modify
49
49
    char argsbuffer[HUGE_STRING_LEN];
50
50
    char *newline;
51
51
    apr_status_t rv;
52
 
    
 
52
 
53
53
    while ((rv = apr_file_gets(argsbuffer, HUGE_STRING_LEN,
54
54
                         script_err)) == APR_SUCCESS) {
55
55
        newline = strchr(argsbuffer, '\n');
59
59
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
60
60
                      "%s", argsbuffer);
61
61
    }
62
 
    
 
62
 
63
63
    return rv;
64
64
}
65
65
 
69
69
    char *next_byte;
70
70
    char *last_byte;
71
71
    apr_bucket *b;
72
 
    
 
72
 
73
73
    if (bytes == 0) {
74
74
        return NULL;
75
75
    }
76
 
    
 
76
 
77
77
    target_buf = (char *) apr_palloc(p, bytes + 1);
78
78
    next_byte = target_buf;
79
79
    last_byte = target_buf + bytes;
80
 
    
 
80
 
81
81
    for (b = APR_BRIGADE_FIRST(bb); b != APR_BRIGADE_SENTINEL(bb); b = APR_BUCKET_NEXT(b)) {
82
82
        char *buf;
83
83
        apr_size_t size;
130
130
static void *suphp_create_dir_config(apr_pool_t *p, char *dir)
131
131
{
132
132
    suphp_conf *cfg = (suphp_conf *) apr_pcalloc(p, sizeof(suphp_conf));
133
 
    
 
133
 
134
134
    cfg->php_config = NULL;
135
135
    cfg->engine = SUPHP_ENGINE_UNDEFINED;
136
136
    cfg->php_path = NULL;
140
140
    cfg->target_user = NULL;
141
141
    cfg->target_group = NULL;
142
142
#endif
143
 
    
 
143
 
144
144
    /* Create table with 0 initial elements */
145
145
    /* This size may be increased for performance reasons */
146
146
    cfg->handlers = apr_table_make(p, 0);
147
 
    
 
147
 
148
148
    return (void *) cfg;
149
149
}
150
150
 
151
151
 
152
 
static void *suphp_merge_dir_config(apr_pool_t *p, void *base, 
 
152
static void *suphp_merge_dir_config(apr_pool_t *p, void *base,
153
153
                                    void *overrides)
154
154
{
155
155
    suphp_conf *parent = (suphp_conf *) base;
156
156
    suphp_conf *child = (suphp_conf *) overrides;
157
157
    suphp_conf *merged = (suphp_conf *) apr_pcalloc(p, sizeof(suphp_conf));
158
 
    
 
158
 
159
159
    merged->cmode = SUPHP_CONFIG_MODE_DIRECTORY;
160
 
    
 
160
 
161
161
    if (child->php_config)
162
162
        merged->php_config = apr_pstrdup(p, child->php_config);
163
163
    else if (parent->php_config)
164
164
        merged->php_config = apr_pstrdup(p, parent->php_config);
165
165
    else
166
166
        merged->php_config = NULL;
167
 
    
 
167
 
168
168
    if (child->engine != SUPHP_ENGINE_UNDEFINED)
169
169
        merged->engine = child->engine;
170
170
    else
177
177
        merged->target_user = apr_pstrdup(p, parent->target_user);
178
178
    else
179
179
        merged->target_user = NULL;
180
 
        
 
180
 
181
181
    if (child->target_group)
182
182
        merged->target_group = apr_pstrdup(p, child->target_group);
183
183
    else if (parent->target_group)
185
185
    else
186
186
        merged->target_group = NULL;
187
187
#endif
188
 
    
 
188
 
189
189
    merged->handlers = apr_table_overlay(p, child->handlers, parent->handlers);
190
 
    
191
 
    return (void *) merged;  
 
190
 
 
191
    return (void *) merged;
192
192
}
193
193
 
194
194
 
195
195
static void *suphp_create_server_config(apr_pool_t *p, server_rec *s)
196
196
{
197
197
    suphp_conf *cfg = (suphp_conf *) apr_pcalloc(p, sizeof(suphp_conf));
198
 
    
 
198
 
199
199
    cfg->engine = SUPHP_ENGINE_UNDEFINED;
200
200
    cfg->php_path = NULL;
201
201
    cfg->cmode = SUPHP_CONFIG_MODE_SERVER;
202
 
    
 
202
 
203
203
    /* Create table with 0 initial elements */
204
204
    /* This size may be increased for performance reasons */
205
205
    cfg->handlers = apr_table_make(p, 0);
206
 
    
 
206
 
207
207
    return (void *) cfg;
208
208
}
209
209
 
214
214
    suphp_conf *parent = (suphp_conf *) base;
215
215
    suphp_conf *child = (suphp_conf *) overrides;
216
216
    suphp_conf *merged = (suphp_conf *) apr_pcalloc(p, sizeof(suphp_conf));
217
 
    
 
217
 
218
218
    if (child->engine != SUPHP_ENGINE_UNDEFINED)
219
219
        merged->engine = child->engine;
220
220
    else
221
221
        merged->engine = parent->engine;
222
 
    
 
222
 
223
223
    if (child->php_path != NULL)
224
224
        merged->php_path = apr_pstrdup(p, child->php_path);
225
225
    else
226
226
        merged->php_path = apr_pstrdup(p, parent->php_path);
227
 
    
 
227
 
228
228
#ifdef SUPHP_USE_USERGROUP
229
229
    if (child->target_user)
230
230
        merged->target_user = apr_pstrdup(p, child->target_user);
232
232
        merged->target_user = apr_pstrdup(p, parent->target_user);
233
233
    else
234
234
        merged->target_user = NULL;
235
 
        
 
235
 
236
236
    if (child->target_group)
237
237
        merged->target_group = apr_pstrdup(p, child->target_group);
238
238
    else if (parent->target_group)
240
240
    else
241
241
        merged->target_group = NULL;
242
242
#endif
243
 
    
 
243
 
244
244
    merged->handlers = apr_table_overlay(p, child->handlers, parent->handlers);
245
 
    
 
245
 
246
246
    return (void*) merged;
247
247
}
248
248
 
256
256
{
257
257
    server_rec *s = cmd->server;
258
258
    suphp_conf *cfg;
259
 
    
 
259
 
260
260
    if (mconfig)
261
261
        cfg = (suphp_conf *) mconfig;
262
262
    else
263
263
        cfg = (suphp_conf *) ap_get_module_config(s->module_config, &suphp_module);
264
 
    
 
264
 
265
265
    if (flag)
266
266
        cfg->engine = SUPHP_ENGINE_ON;
267
267
    else
268
268
        cfg->engine = SUPHP_ENGINE_OFF;
269
 
    
 
269
 
270
270
    return NULL;
271
271
}
272
272
 
276
276
{
277
277
    server_rec *s = cmd->server;
278
278
    suphp_conf *cfg;
279
 
    
 
279
 
280
280
    if (mconfig)
281
281
        cfg = (suphp_conf *) mconfig;
282
282
    else
283
283
        cfg = (suphp_conf *) ap_get_module_config(s->module_config, &suphp_module);
284
 
    
 
284
 
285
285
    cfg->php_config = apr_pstrdup(cmd->pool, arg);
286
 
    
 
286
 
287
287
    return NULL;
288
288
}
289
289
 
293
293
                                           const char *arg1, const char *arg2)
294
294
{
295
295
    suphp_conf *cfg = (suphp_conf *) mconfig;
296
 
    
 
296
 
297
297
    cfg->target_user = apr_pstrdup(cmd->pool, arg1);
298
298
    cfg->target_group = apr_pstrdup(cmd->pool, arg2);
299
 
    
 
299
 
300
300
    return NULL;
301
301
}
302
302
#endif
310
310
        cfg = (suphp_conf *) mconfig;
311
311
    else
312
312
        cfg = (suphp_conf *) ap_get_module_config(cmd->server->module_config, &suphp_module);
313
 
    
 
313
 
314
314
    // Mark active handler with '1'
315
315
    apr_table_set(cfg->handlers, arg, "1");
316
316
 
318
318
}
319
319
 
320
320
 
321
 
static const char *suphp_handle_cmd_remove_handler(cmd_parms *cmd, 
322
 
                                                   void *mconfig, 
 
321
static const char *suphp_handle_cmd_remove_handler(cmd_parms *cmd,
 
322
                                                   void *mconfig,
323
323
                                                   const char *arg)
324
324
{
325
325
    suphp_conf *cfg;
327
327
        cfg = (suphp_conf *) mconfig;
328
328
    else
329
329
        cfg = (suphp_conf *) ap_get_module_config(cmd->server->module_config, &suphp_module);
330
 
    
 
330
 
331
331
    // Mark deactivated handler with '0'
332
332
    apr_table_set(cfg->handlers, arg, "0");
333
333
 
339
339
{
340
340
    server_rec *s = cmd->server;
341
341
    suphp_conf *cfg;
342
 
    
 
342
 
343
343
    cfg = (suphp_conf *) ap_get_module_config(s->module_config, &suphp_module);
344
 
    
 
344
 
345
345
    cfg->php_path = apr_pstrdup(cmd->pool, arg);
346
 
    
 
346
 
347
347
    return NULL;
348
348
}
349
349
 
384
384
    apr_status_t rv;
385
385
    apr_pollfd_t fd;
386
386
    struct suphp_bucket_data *data = apr_palloc(r->pool, sizeof(*data));
387
 
    
 
387
 
388
388
    APR_BUCKET_INIT(b);
389
389
    b->free = apr_bucket_free;
390
390
    b->list = list;
391
391
    b->type = &bucket_type_suphp;
392
392
    b->length = (apr_size_t) (-1);
393
393
    b->start = (-1);
394
 
    
 
394
 
395
395
    /* Create the pollset */
396
396
    rv = apr_pollset_create(&data->pollset, 2, r->pool, 0);
397
397
    AP_DEBUG_ASSERT(rv == APR_SUCCESS);
398
 
    
 
398
 
399
399
    fd.desc_type = APR_POLL_FILE;
400
400
    fd.reqevents = APR_POLLIN;
401
401
    fd.p = r->pool;
403
403
    fd.client_data = (void *) 1;
404
404
    rv = apr_pollset_add(data->pollset, &fd);
405
405
    AP_DEBUG_ASSERT(rv == APR_SUCCESS);
406
 
    
 
406
 
407
407
    fd.desc.f = err; /* script's stderr */
408
408
    fd.client_data = (void *) 2;
409
409
    rv = apr_pollset_add(data->pollset, &fd);
410
410
    AP_DEBUG_ASSERT(rv == APR_SUCCESS);
411
 
    
 
411
 
412
412
    data->r = r;
413
413
    b->data = data;
414
414
    return b;
433
433
{
434
434
    char *buf;
435
435
    apr_status_t rv;
436
 
    
 
436
 
437
437
    *str = NULL;
438
438
    *len = APR_BUCKET_BUFF_SIZE;
439
439
    buf = apr_bucket_alloc(*len, b->list);
440
 
    
 
440
 
441
441
    rv = apr_file_read(fd, buf, len);
442
 
    
 
442
 
443
443
    if (*len > 0) {
444
444
        /* Got data */
445
445
        struct suphp_bucket_data *data = b->data;
446
446
        apr_bucket_heap *h;
447
 
        
 
447
 
448
448
        /* Change the current bucket to refer to what we read
449
449
           and append the pipe bucket after it                */
450
450
        b = apr_bucket_heap_make(b, buf, *len, apr_bucket_free);
470
470
  apr_interval_time_t timeout;
471
471
  apr_status_t rv;
472
472
  int gotdata = 0;
473
 
  
 
473
 
474
474
  timeout = (block == APR_NONBLOCK_READ) ? 0 : data->r->server->timeout;
475
 
  
 
475
 
476
476
  do {
477
477
      const apr_pollfd_t *results;
478
478
      apr_int32_t num;
479
 
      
 
479
 
480
480
      rv = apr_pollset_poll(data->pollset, timeout, &num, &results);
481
481
      if (APR_STATUS_IS_TIMEUP(rv)) {
482
482
          return (timeout == 0) ? APR_EAGAIN : rv;
486
486
          ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, data->r, "Poll failed waiting for suPHP child process");
487
487
          return rv;
488
488
      }
489
 
      
 
489
 
490
490
      while (num > 0) {
491
491
        if (results[0].client_data == (void *) 1) {
492
492
            /* handle stdout */
506
506
        results++;
507
507
      }
508
508
  } while (!gotdata);
509
 
  
 
509
 
510
510
  return rv;
511
511
}
512
512
 
548
548
static int suphp_handler(request_rec *r)
549
549
{
550
550
    suphp_conf *sconf, *dconf;
551
 
    
 
551
 
552
552
    sconf = ap_get_module_config(r->server->module_config, &suphp_module);
553
553
    dconf = ap_get_module_config(r->per_dir_config, &suphp_module);
554
 
    
 
554
 
555
555
    /* only handle request if mod_suphp is active for this handler */
556
556
    /* check only first byte of value (second has to be \0) */
557
557
    if (apr_table_get(dconf->handlers, r->handler) != NULL)
569
569
            return suphp_script_handler(r);
570
570
        }
571
571
    }
572
 
    
573
 
    if (!strcmp(r->handler, "x-httpd-php-source") 
 
572
 
 
573
    if (!strcmp(r->handler, "x-httpd-php-source")
574
574
    || !strcmp(r->handler, "application/x-httpd-php-source"))
575
575
    {
576
576
        return suphp_source_handler(r);
577
577
    }
578
 
    
 
578
 
579
579
    return DECLINED;
580
580
}
581
581
 
583
583
{
584
584
    suphp_conf *conf;
585
585
    apr_status_t rv;
586
 
    apr_pool_t *p;
 
586
    apr_pool_t *p = r->main ? r->main->pool : r->pool;
587
587
    apr_file_t *file;
588
588
    apr_proc_t *proc;
589
589
    apr_procattr_t *procattr;
592
592
    apr_bucket_brigade *bb;
593
593
    apr_bucket *b;
594
594
    char *phpexec;
595
 
    
596
 
    p = r->main ? r->main->pool : r->pool;
597
 
    
 
595
    apr_table_t *empty_table = apr_table_make(p, 0);
 
596
 
598
597
    if (strcmp(r->method, "GET"))
599
598
    {
600
599
        return DECLINED;
601
600
    }
602
 
    
 
601
 
603
602
    conf = ap_get_module_config(r->server->module_config, &suphp_module);
604
603
    phpexec = apr_pstrdup(p, conf->php_path);
605
604
    if (phpexec == NULL)
606
605
    {
607
606
        return DECLINED;
608
607
    }
609
 
    
 
608
 
610
609
    // Try to open file for reading to see whether is is accessible
611
610
    rv = apr_file_open(&file, apr_pstrdup(p, r->filename), APR_READ, APR_OS_DEFAULT, p);
612
611
    if (rv == APR_SUCCESS)
629
628
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "Could not open file: %s", r->filename);
630
629
        return HTTP_INTERNAL_SERVER_ERROR;
631
630
    }
632
 
    
633
 
        env = ap_create_environment(p, r->subprocess_env);
634
 
        
 
631
 
635
632
    /* set attributes for new process */
636
 
    
 
633
 
637
634
    if (((rv = apr_procattr_create(&procattr, p)) != APR_SUCCESS)
638
635
        || ((rv = apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK)) != APR_SUCCESS)
639
636
        || ((rv = apr_procattr_dir_set(procattr, ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS)
646
643
        return HTTP_INTERNAL_SERVER_ERROR;
647
644
    }
648
645
 
649
 
    
 
646
 
650
647
    /* create new process */
651
 
    
 
648
 
652
649
    argv = apr_palloc(p, 4 * sizeof(char *));
653
650
    argv[0] = phpexec;
654
651
    argv[1] = "-s";
655
652
    argv[2] = apr_pstrdup(p, r->filename);
656
653
    argv[3] = NULL;
657
 
    
658
 
    env = ap_create_environment(p, r->subprocess_env);
659
 
    
 
654
 
 
655
    env = ap_create_environment(p, empty_table);
 
656
 
660
657
    proc = apr_pcalloc(p, sizeof(*proc));
661
658
    rv = apr_proc_create(proc, phpexec, (const char *const *)argv, (const char *const *)env, procattr, p);
662
659
    if (rv != APR_SUCCESS)
670
667
    if (!proc->out)
671
668
        return APR_EBADF;
672
669
    apr_file_pipe_timeout_set(proc->out, r->server->timeout);
673
 
    
 
670
 
674
671
    if (!proc->in)
675
672
        return APR_EBADF;
676
673
    apr_file_pipe_timeout_set(proc->in, r->server->timeout);
677
 
    
 
674
 
678
675
    if (!proc->err)
679
676
        return APR_EBADF;
680
677
    apr_file_pipe_timeout_set(proc->err, r->server->timeout);
681
 
    
 
678
 
682
679
    /* discard input */
683
 
        
 
680
 
684
681
    bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
685
 
    
 
682
 
686
683
    apr_file_flush(proc->in);
687
684
    apr_file_close(proc->in);
688
 
    
 
685
 
689
686
    rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, APR_BLOCK_READ, HUGE_STRING_LEN);
690
687
    if (rv != APR_SUCCESS)
691
688
    {
695
692
    }
696
693
    suphp_discard_output(bb);
697
694
    apr_brigade_cleanup(bb);
698
 
    
 
695
 
699
696
    /* get output from script */
700
 
    
 
697
 
701
698
#if APR_FILES_AS_SOCKETS
702
699
    apr_file_pipe_timeout_set(proc->out, 0);
703
700
    apr_file_pipe_timeout_set(proc->err, 0);
706
703
    b = apr_bucket_pipe_create(proc->out, r->connection->bucket_alloc);
707
704
#endif
708
705
    APR_BRIGADE_INSERT_TAIL(bb, b);
709
 
    
 
706
 
710
707
    b = apr_bucket_eos_create(r->connection->bucket_alloc);
711
708
    APR_BRIGADE_INSERT_TAIL(bb, b);
712
709
 
713
710
    /* send output to browser (through filters) */
714
 
    
 
711
 
715
712
    r->content_type = "text/html";
716
713
    rv = ap_pass_brigade(r->output_filters, bb);
717
 
    
 
714
 
718
715
    /* write errors to logfile */
719
 
    
 
716
 
720
717
    if (rv == APR_SUCCESS && !r->connection->aborted)
721
718
    {
722
719
        suphp_log_script_err(r, proc->err);
723
720
        apr_file_close(proc->err);
724
721
    }
725
 
    
 
722
 
726
723
    return OK;
727
724
}
728
725
 
732
729
    suphp_conf *sconf;
733
730
    suphp_conf *dconf;
734
731
    core_dir_config *core_conf;
735
 
    
 
732
 
736
733
    apr_finfo_t finfo;
737
 
    
 
734
 
738
735
    apr_procattr_t *procattr;
739
 
    
 
736
 
740
737
    apr_proc_t *proc;
741
 
    
 
738
 
742
739
    char **argv;
743
740
    char **env;
744
741
    apr_status_t rv;
758
755
    char *ud_user = NULL;
759
756
    char *ud_group = NULL;
760
757
#endif
761
 
    
 
758
 
762
759
    apr_bucket_brigade *bb;
763
760
    apr_bucket *b;
764
 
    
 
761
 
765
762
    /* load configuration */
766
 
    
 
763
 
767
764
    p = r->main ? r->main->pool : r->pool;
768
765
    sconf = ap_get_module_config(r->server->module_config, &suphp_module);
769
766
    dconf = ap_get_module_config(r->per_dir_config, &suphp_module);
770
767
    core_conf = (core_dir_config *) ap_get_module_config(r->per_dir_config, &core_module);
771
 
    
 
768
 
772
769
    /* check if suPHP is enabled for this request */
773
 
    
 
770
 
774
771
    if (((sconf->engine != SUPHP_ENGINE_ON)
775
772
        && (dconf->engine != SUPHP_ENGINE_ON))
776
773
        || ((sconf->engine == SUPHP_ENGINE_ON)
777
774
        && (dconf->engine == SUPHP_ENGINE_OFF)))
778
775
        return DECLINED;
779
 
    
 
776
 
780
777
    /* check if file is existing and acessible */
781
 
    
 
778
 
782
779
    rv = apr_stat(&finfo, apr_pstrdup(p, r->filename), APR_FINFO_NORM, p);
783
 
    
 
780
 
784
781
    if (rv == APR_SUCCESS)
785
782
        ; /* do nothing */
786
783
    else if (rv == EACCES)
798
795
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "could not get fileinfo: %s", r->filename);
799
796
        return HTTP_NOT_FOUND;
800
797
    }
801
 
    
 
798
 
802
799
    if (!(r->finfo.protection & APR_UREAD))
803
800
    {
804
801
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Insufficient permissions: %s", r->filename);
805
802
        return HTTP_FORBIDDEN;
806
803
    }
807
 
    
 
804
 
808
805
#ifdef SUPHP_USE_USERGROUP
809
806
    if ((sconf->target_user == NULL || sconf->target_group == NULL)
810
807
        && (dconf->target_user == NULL || dconf->target_group == NULL))
816
813
            ud_user = apr_psprintf(r->pool, "#%ld", (long) userdir_id->uid);
817
814
            ud_group = apr_psprintf(r->pool, "#%ld", (long) userdir_id->gid);
818
815
        } else {
819
 
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 
 
816
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
820
817
                          "No user or group set - set suPHP_UserGroup");
821
818
            return HTTP_INTERNAL_SERVER_ERROR;
822
819
        }
823
820
    }
824
821
#endif
825
 
        
 
822
 
826
823
    /* prepare argv for new process */
827
 
    
 
824
 
828
825
    argv = apr_palloc(p, 2 * sizeof(char *));
829
826
    argv[0] = SUPHP_PATH_TO_SUPHP;
830
827
    argv[1] = NULL;
831
 
    
 
828
 
832
829
    /* prepare environment for new process */
833
 
    
 
830
 
834
831
    ap_add_common_vars(r);
835
832
    ap_add_cgi_vars(r);
836
 
    
 
833
 
837
834
    apr_table_unset(r->subprocess_env, "SUPHP_PHP_CONFIG");
838
835
    apr_table_unset(r->subprocess_env, "SUPHP_AUTH_USER");
839
836
    apr_table_unset(r->subprocess_env, "SUPHP_AUTH_PW");
840
 
    
 
837
 
841
838
#ifdef SUPHP_USE_USERGROUP
842
839
    apr_table_unset(r->subprocess_env, "SUPHP_USER");
843
840
    apr_table_unset(r->subprocess_env, "SUPHP_GROUP");
844
841
#endif
845
 
    
 
842
 
846
843
    if (dconf->php_config)
847
844
    {
848
845
        apr_table_setn(r->subprocess_env, "SUPHP_PHP_CONFIG", apr_pstrdup(p, dconf->php_config));
849
846
    }
850
 
    
 
847
 
851
848
    apr_table_setn(r->subprocess_env, "SUPHP_HANDLER", r->handler);
852
 
    
 
849
 
853
850
    if (r->headers_in)
854
851
    {
855
852
        const char *auth = NULL;
871
868
            }
872
869
        }
873
870
    }
874
 
    
 
871
 
875
872
    if (auth_user && auth_pass)
876
873
    {
877
874
        apr_table_setn(r->subprocess_env, "SUPHP_AUTH_USER", auth_user);
894
891
        apr_table_setn(r->subprocess_env, "SUPHP_USER",
895
892
                       apr_pstrdup(r->pool, ud_user));
896
893
    }
897
 
    
 
894
 
898
895
    if (dconf->target_group)
899
896
    {
900
897
        apr_table_setn(r->subprocess_env, "SUPHP_GROUP",
911
908
                       apr_pstrdup(r->pool, ud_group));
912
909
    }
913
910
#endif
914
 
    
 
911
 
915
912
    env = ap_create_environment(p, r->subprocess_env);
916
 
        
 
913
 
917
914
    /* set attributes for new process */
918
 
    
 
915
 
919
916
    if (((rv = apr_procattr_create(&procattr, p)) != APR_SUCCESS)
920
917
        || ((rv = apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK)) != APR_SUCCESS)
921
918
        || ((rv = apr_procattr_dir_set(procattr, ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS)
922
 
    
 
919
 
923
920
    /* set resource limits */
924
921
 
925
922
#ifdef RLIMIT_CPU
940
937
                      "couldn't set child process attributes: %s", r->filename);
941
938
        return HTTP_INTERNAL_SERVER_ERROR;
942
939
    }
943
 
    
 
940
 
944
941
    /* create new process */
945
 
    
 
942
 
946
943
 
947
944
    proc = apr_pcalloc(p, sizeof(*proc));
948
945
    rv = apr_proc_create(proc, SUPHP_PATH_TO_SUPHP, (const char *const *)argv, (const char *const *)env, procattr, p);
957
954
    if (!proc->out)
958
955
        return APR_EBADF;
959
956
    apr_file_pipe_timeout_set(proc->out, r->server->timeout);
960
 
    
 
957
 
961
958
    if (!proc->in)
962
959
        return APR_EBADF;
963
960
    apr_file_pipe_timeout_set(proc->in, r->server->timeout);
964
 
    
 
961
 
965
962
    if (!proc->err)
966
963
        return APR_EBADF;
967
964
    apr_file_pipe_timeout_set(proc->err, r->server->timeout);
968
 
    
 
965
 
969
966
    /* send request body to script */
970
 
    
 
967
 
971
968
    bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
972
969
    do
973
970
    {
974
971
        apr_bucket *bucket;
975
972
        rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, APR_BLOCK_READ, HUGE_STRING_LEN);
976
 
        
 
973
 
977
974
        if (rv != APR_SUCCESS)
978
975
        {
979
976
            return rv;
980
977
        }
981
 
        
 
978
 
982
979
        for (bucket = APR_BRIGADE_FIRST(bb); bucket != APR_BRIGADE_SENTINEL(bb); bucket = APR_BUCKET_NEXT(bucket))
983
980
        {
984
981
            const char *data;
985
982
            apr_size_t len;
986
983
            int child_stopped_reading = 0;
987
 
            
 
984
 
988
985
            if (APR_BUCKET_IS_EOS(bucket))
989
986
            {
990
987
                eos_reached = 1;
991
988
                break;
992
989
            }
993
 
            
 
990
 
994
991
            if (APR_BUCKET_IS_FLUSH(bucket) || child_stopped_reading)
995
992
            {
996
993
                continue;
997
994
            }
998
 
            
 
995
 
999
996
            apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
1000
 
            
 
997
 
1001
998
            rv = apr_file_write_full(proc->in, data, len, NULL);
1002
999
            if (rv != APR_SUCCESS)
1003
1000
            {
1007
1004
        apr_brigade_cleanup(bb);
1008
1005
    }
1009
1006
    while (!eos_reached);
1010
 
    
 
1007
 
1011
1008
    apr_file_flush(proc->in);
1012
1009
    apr_file_close(proc->in);
1013
 
    
 
1010
 
1014
1011
    /* get output from script and check if non-parsed headers are used */
1015
 
    
 
1012
 
1016
1013
#if APR_FILES_AS_SOCKETS
1017
1014
    apr_file_pipe_timeout_set(proc->out, 0);
1018
1015
    apr_file_pipe_timeout_set(proc->err, 0);
1022
1019
#endif
1023
1020
 
1024
1021
    APR_BRIGADE_INSERT_TAIL(bb, b);
1025
 
    
 
1022
 
1026
1023
    b = apr_bucket_eos_create(r->connection->bucket_alloc);
1027
1024
    APR_BRIGADE_INSERT_TAIL(bb, b);
1028
1025
 
1031
1028
    {
1032
1029
        nph = 1;
1033
1030
    }
1034
 
    
 
1031
 
1035
1032
    if (!nph)
1036
1033
    {
1037
1034
        /* normal cgi headers, so we have to create the real headers ourselves */
1038
 
        
 
1035
 
1039
1036
        int ret;
1040
1037
        const char *location;
1041
 
    
 
1038
 
1042
1039
        ret = ap_scan_script_header_err_brigade(r, bb, strbuf);
1043
1040
        if (ret == HTTP_NOT_MODIFIED)
1044
1041
        {
1049
1046
            suphp_discard_output(bb);
1050
1047
            apr_brigade_destroy(bb);
1051
1048
            suphp_log_script_err(r, proc->err);
1052
 
            
 
1049
 
1053
1050
            /* ap_scan_script_header_err_brigade does logging itself,
1054
1051
               so simply return                                       */
1055
 
               
 
1052
 
1056
1053
            return HTTP_INTERNAL_SERVER_ERROR;
1057
1054
        }
1058
 
        
 
1055
 
1059
1056
        location = apr_table_get(r->headers_out, "Location");
1060
1057
        if (location && location[0] == '/' && r->status == 200)
1061
1058
        {
1062
1059
            /* empty brigade (script output) and modify headers */
1063
 
            
 
1060
 
1064
1061
            suphp_discard_output(bb);
1065
1062
            apr_brigade_destroy(bb);
1066
1063
            suphp_log_script_err(r, proc->err);
1067
1064
            r->method = apr_pstrdup(r->pool, "GET");
1068
1065
            r->method_number = M_GET;
1069
1066
            apr_table_unset(r->headers_in, "Content-Length");
1070
 
            
 
1067
 
1071
1068
            ap_internal_redirect_handler(location, r);
1072
1069
            return OK;
1073
1070
        }
1079
1076
            suphp_log_script_err(r, proc->err);
1080
1077
            return HTTP_MOVED_TEMPORARILY;
1081
1078
        }
1082
 
        
 
1079
 
1083
1080
        /* send output to browser (through filters) */
1084
 
        
 
1081
 
1085
1082
        rv = ap_pass_brigade(r->output_filters, bb);
1086
 
        
 
1083
 
1087
1084
        /* write errors to logfile */
1088
 
        
 
1085
 
1089
1086
        if (rv == APR_SUCCESS && !r->connection->aborted)
1090
1087
            suphp_log_script_err(r, proc->err);
1091
 
        
 
1088
 
1092
1089
        apr_file_close(proc->err);
1093
1090
    }
1094
 
    
 
1091
 
1095
1092
    if (proc->out && nph)
1096
1093
    {
1097
1094
        /* use non-parsed headers (direct output) */
1098
 
        
 
1095
 
1099
1096
        struct ap_filter_t *cur;
1100
 
        
 
1097
 
1101
1098
        /* get rid of output filters */
1102
 
        
 
1099
 
1103
1100
        cur = r->proto_output_filters;
1104
1101
        while (cur && cur->frec->ftype < AP_FTYPE_CONNECTION)
1105
1102
        {
1106
1103
            cur = cur->next;
1107
1104
        }
1108
1105
        r->output_filters = r->proto_output_filters = cur;
1109
 
        
 
1106
 
1110
1107
        /* send output to browser (directly) */
1111
 
        
 
1108
 
1112
1109
        rv = ap_pass_brigade(r->output_filters, bb);
1113
 
        
 
1110
 
1114
1111
        /* log errors */
1115
1112
        if (rv == APR_SUCCESS && !r->connection->aborted)
1116
1113
            suphp_log_script_err(r, proc->err);
1117
 
            
 
1114
 
1118
1115
        apr_file_close(proc->err);
1119
1116
    }
1120
1117
 
1130
1127
/********************
1131
1128
  Module declaration
1132
1129
 ********************/
1133
 
 
 
1130
 
1134
1131
module AP_MODULE_DECLARE_DATA suphp_module =
1135
1132
{
1136
1133
    STANDARD20_MODULE_STUFF,