@@ -3063,6 +3063,23 @@ PHP_FUNCTION(imap_fetch_overview)
3063
3063
}
3064
3064
/* }}} */
3065
3065
3066
+ static zend_bool header_injection (zend_string * str , zend_bool adrlist )
3067
+ {
3068
+ char * p = ZSTR_VAL (str );
3069
+
3070
+ while ((p = strpbrk (p , "\r\n" )) != NULL ) {
3071
+ if (!(p [0 ] == '\r' && p [1 ] == '\n' )
3072
+ /* adrlists do not support folding, but swallow trailing line breaks */
3073
+ && !((adrlist && p [1 ] == '\0' )
3074
+ /* other headers support folding */
3075
+ || !adrlist && (p [1 ] == ' ' || p [1 ] == '\t' ))) {
3076
+ return 1 ;
3077
+ }
3078
+ p ++ ;
3079
+ }
3080
+ return 0 ;
3081
+ }
3082
+
3066
3083
/* {{{ Create a MIME message based on given envelope and body sections */
3067
3084
PHP_FUNCTION (imap_mail_compose )
3068
3085
{
@@ -3086,6 +3103,13 @@ PHP_FUNCTION(imap_mail_compose)
3086
3103
zend_argument_value_error (2 , "cannot be empty" );
3087
3104
}
3088
3105
3106
+ #define CHECK_HEADER_INJECTION (zstr , adrlist , header ) \
3107
+ if (header_injection(zstr, adrlist)) { \
3108
+ php_error_docref(NULL, E_WARNING, "header injection attempt in " header); \
3109
+ RETVAL_FALSE; \
3110
+ goto done; \
3111
+ }
3112
+
3089
3113
#define PHP_RFC822_PARSE_ADRLIST (target , value ) \
3090
3114
str_copy = estrndup(Z_STRVAL_P(value), Z_STRLEN_P(value)); \
3091
3115
rfc822_parse_adrlist(target, str_copy, "NO HOST"); \
@@ -3094,46 +3118,57 @@ PHP_FUNCTION(imap_mail_compose)
3094
3118
env = mail_newenvelope ();
3095
3119
if ((pvalue = zend_hash_str_find (envelope , "remail" , sizeof ("remail" ) - 1 )) != NULL ) {
3096
3120
convert_to_string_ex (pvalue );
3121
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "remail" );
3097
3122
env -> remail = cpystr (Z_STRVAL_P (pvalue ));
3098
3123
}
3099
3124
if ((pvalue = zend_hash_str_find (envelope , "return_path" , sizeof ("return_path" ) - 1 )) != NULL ) {
3100
3125
convert_to_string_ex (pvalue );
3126
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 1 , "return_path" );
3101
3127
PHP_RFC822_PARSE_ADRLIST (& env -> return_path , pvalue );
3102
3128
}
3103
3129
if ((pvalue = zend_hash_str_find (envelope , "date" , sizeof ("date" ) - 1 )) != NULL ) {
3104
3130
convert_to_string_ex (pvalue );
3131
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "date" );
3105
3132
env -> date = (unsigned char * )cpystr (Z_STRVAL_P (pvalue ));
3106
3133
}
3107
3134
if ((pvalue = zend_hash_str_find (envelope , "from" , sizeof ("from" ) - 1 )) != NULL ) {
3108
3135
convert_to_string_ex (pvalue );
3136
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 1 , "from" );
3109
3137
PHP_RFC822_PARSE_ADRLIST (& env -> from , pvalue );
3110
3138
}
3111
3139
if ((pvalue = zend_hash_str_find (envelope , "reply_to" , sizeof ("reply_to" ) - 1 )) != NULL ) {
3112
3140
convert_to_string_ex (pvalue );
3141
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 1 , "reply_to" );
3113
3142
PHP_RFC822_PARSE_ADRLIST (& env -> reply_to , pvalue );
3114
3143
}
3115
3144
if ((pvalue = zend_hash_str_find (envelope , "in_reply_to" , sizeof ("in_reply_to" ) - 1 )) != NULL ) {
3116
3145
convert_to_string_ex (pvalue );
3146
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "in_reply_to" );
3117
3147
env -> in_reply_to = cpystr (Z_STRVAL_P (pvalue ));
3118
3148
}
3119
3149
if ((pvalue = zend_hash_str_find (envelope , "subject" , sizeof ("subject" ) - 1 )) != NULL ) {
3120
3150
convert_to_string_ex (pvalue );
3151
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "subject" );
3121
3152
env -> subject = cpystr (Z_STRVAL_P (pvalue ));
3122
3153
}
3123
3154
if ((pvalue = zend_hash_str_find (envelope , "to" , sizeof ("to" ) - 1 )) != NULL ) {
3124
3155
convert_to_string_ex (pvalue );
3156
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 1 , "to" );
3125
3157
PHP_RFC822_PARSE_ADRLIST (& env -> to , pvalue );
3126
3158
}
3127
3159
if ((pvalue = zend_hash_str_find (envelope , "cc" , sizeof ("cc" ) - 1 )) != NULL ) {
3128
3160
convert_to_string_ex (pvalue );
3161
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 1 , "cc" );
3129
3162
PHP_RFC822_PARSE_ADRLIST (& env -> cc , pvalue );
3130
3163
}
3131
3164
if ((pvalue = zend_hash_str_find (envelope , "bcc" , sizeof ("bcc" ) - 1 )) != NULL ) {
3132
3165
convert_to_string_ex (pvalue );
3166
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 1 , "bcc" );
3133
3167
PHP_RFC822_PARSE_ADRLIST (& env -> bcc , pvalue );
3134
3168
}
3135
3169
if ((pvalue = zend_hash_str_find (envelope , "message_id" , sizeof ("message_id" ) - 1 )) != NULL ) {
3136
3170
convert_to_string_ex (pvalue );
3171
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "message_id" );
3137
3172
env -> message_id = cpystr (Z_STRVAL_P (pvalue ));
3138
3173
}
3139
3174
@@ -3144,6 +3179,7 @@ PHP_FUNCTION(imap_mail_compose)
3144
3179
ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (pvalue ), env_data ) {
3145
3180
custom_headers_param = mail_newbody_parameter ();
3146
3181
convert_to_string_ex (env_data );
3182
+ CHECK_HEADER_INJECTION (Z_STR_P (env_data ), 0 , "custom_headers" );
3147
3183
custom_headers_param -> value = (char * ) fs_get (Z_STRLEN_P (env_data ) + 1 );
3148
3184
custom_headers_param -> attribute = NULL ;
3149
3185
memcpy (custom_headers_param -> value , Z_STRVAL_P (env_data ), Z_STRLEN_P (env_data ) + 1 );
@@ -3186,6 +3222,7 @@ PHP_FUNCTION(imap_mail_compose)
3186
3222
}
3187
3223
if ((pvalue = zend_hash_str_find (Z_ARRVAL_P (data ), "charset" , sizeof ("charset" ) - 1 )) != NULL ) {
3188
3224
convert_to_string_ex (pvalue );
3225
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "body charset" );
3189
3226
tmp_param = mail_newbody_parameter ();
3190
3227
tmp_param -> value = cpystr (Z_STRVAL_P (pvalue ));
3191
3228
tmp_param -> attribute = cpystr ("CHARSET" );
@@ -3198,9 +3235,11 @@ PHP_FUNCTION(imap_mail_compose)
3198
3235
SEPARATE_ARRAY (pvalue );
3199
3236
ZEND_HASH_FOREACH_STR_KEY_VAL (Z_ARRVAL_P (pvalue ), key , disp_data ) {
3200
3237
if (key == NULL ) continue ;
3238
+ CHECK_HEADER_INJECTION (key , 0 , "body disposition key" );
3201
3239
disp_param = mail_newbody_parameter ();
3202
3240
disp_param -> attribute = cpystr (ZSTR_VAL (key ));
3203
3241
convert_to_string_ex (disp_data );
3242
+ CHECK_HEADER_INJECTION (Z_STR_P (disp_data ), 0 , "body disposition value" );
3204
3243
disp_param -> value = (char * ) fs_get (Z_STRLEN_P (disp_data ) + 1 );
3205
3244
memcpy (disp_param -> value , Z_STRVAL_P (disp_data ), Z_STRLEN_P (disp_data ) + 1 );
3206
3245
disp_param -> next = tmp_param ;
@@ -3211,18 +3250,22 @@ PHP_FUNCTION(imap_mail_compose)
3211
3250
}
3212
3251
if ((pvalue = zend_hash_str_find (Z_ARRVAL_P (data ), "subtype" , sizeof ("subtype" ) - 1 )) != NULL ) {
3213
3252
convert_to_string_ex (pvalue );
3253
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "body subtype" );
3214
3254
bod -> subtype = cpystr (Z_STRVAL_P (pvalue ));
3215
3255
}
3216
3256
if ((pvalue = zend_hash_str_find (Z_ARRVAL_P (data ), "id" , sizeof ("id" ) - 1 )) != NULL ) {
3217
3257
convert_to_string_ex (pvalue );
3258
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "body id" );
3218
3259
bod -> id = cpystr (Z_STRVAL_P (pvalue ));
3219
3260
}
3220
3261
if ((pvalue = zend_hash_str_find (Z_ARRVAL_P (data ), "description" , sizeof ("description" ) - 1 )) != NULL ) {
3221
3262
convert_to_string_ex (pvalue );
3263
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "body description" );
3222
3264
bod -> description = cpystr (Z_STRVAL_P (pvalue ));
3223
3265
}
3224
3266
if ((pvalue = zend_hash_str_find (Z_ARRVAL_P (data ), "disposition.type" , sizeof ("disposition.type" ) - 1 )) != NULL ) {
3225
3267
convert_to_string_ex (pvalue );
3268
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "body disposition.type" );
3226
3269
bod -> disposition .type = (char * ) fs_get (Z_STRLEN_P (pvalue ) + 1 );
3227
3270
memcpy (bod -> disposition .type , Z_STRVAL_P (pvalue ), Z_STRLEN_P (pvalue )+ 1 );
3228
3271
}
@@ -3232,9 +3275,11 @@ PHP_FUNCTION(imap_mail_compose)
3232
3275
SEPARATE_ARRAY (pvalue );
3233
3276
ZEND_HASH_FOREACH_STR_KEY_VAL (Z_ARRVAL_P (pvalue ), key , disp_data ) {
3234
3277
if (key == NULL ) continue ;
3278
+ CHECK_HEADER_INJECTION (key , 0 , "body type.parameters key" );
3235
3279
disp_param = mail_newbody_parameter ();
3236
3280
disp_param -> attribute = cpystr (ZSTR_VAL (key ));
3237
3281
convert_to_string_ex (disp_data );
3282
+ CHECK_HEADER_INJECTION (Z_STR_P (disp_data ), 0 , "body type.parameters value" );
3238
3283
disp_param -> value = (char * ) fs_get (Z_STRLEN_P (disp_data ) + 1 );
3239
3284
memcpy (disp_param -> value , Z_STRVAL_P (disp_data ), Z_STRLEN_P (disp_data ) + 1 );
3240
3285
disp_param -> next = tmp_param ;
@@ -3265,6 +3310,7 @@ PHP_FUNCTION(imap_mail_compose)
3265
3310
}
3266
3311
if ((pvalue = zend_hash_str_find (Z_ARRVAL_P (data ), "md5" , sizeof ("md5" ) - 1 )) != NULL ) {
3267
3312
convert_to_string_ex (pvalue );
3313
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "body md5" );
3268
3314
bod -> md5 = cpystr (Z_STRVAL_P (pvalue ));
3269
3315
}
3270
3316
} else if (Z_TYPE_P (data ) == IS_ARRAY && topbod -> type == TYPEMULTIPART ) {
@@ -3297,6 +3343,7 @@ PHP_FUNCTION(imap_mail_compose)
3297
3343
}
3298
3344
if ((pvalue = zend_hash_str_find (Z_ARRVAL_P (data ), "charset" , sizeof ("charset" ) - 1 )) != NULL ) {
3299
3345
convert_to_string_ex (pvalue );
3346
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "body charset" );
3300
3347
tmp_param = mail_newbody_parameter ();
3301
3348
tmp_param -> value = (char * ) fs_get (Z_STRLEN_P (pvalue ) + 1 );
3302
3349
memcpy (tmp_param -> value , Z_STRVAL_P (pvalue ), Z_STRLEN_P (pvalue ) + 1 );
@@ -3310,9 +3357,11 @@ PHP_FUNCTION(imap_mail_compose)
3310
3357
SEPARATE_ARRAY (pvalue );
3311
3358
ZEND_HASH_FOREACH_STR_KEY_VAL (Z_ARRVAL_P (pvalue ), key , disp_data ) {
3312
3359
if (key == NULL ) continue ;
3360
+ CHECK_HEADER_INJECTION (key , 0 , "body type.parameters key" );
3313
3361
disp_param = mail_newbody_parameter ();
3314
3362
disp_param -> attribute = cpystr (ZSTR_VAL (key ));
3315
3363
convert_to_string_ex (disp_data );
3364
+ CHECK_HEADER_INJECTION (Z_STR_P (disp_data ), 0 , "body type.parameters value" );
3316
3365
disp_param -> value = (char * )fs_get (Z_STRLEN_P (disp_data ) + 1 );
3317
3366
memcpy (disp_param -> value , Z_STRVAL_P (disp_data ), Z_STRLEN_P (disp_data ) + 1 );
3318
3367
disp_param -> next = tmp_param ;
@@ -3323,18 +3372,22 @@ PHP_FUNCTION(imap_mail_compose)
3323
3372
}
3324
3373
if ((pvalue = zend_hash_str_find (Z_ARRVAL_P (data ), "subtype" , sizeof ("subtype" ) - 1 )) != NULL ) {
3325
3374
convert_to_string_ex (pvalue );
3375
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "body subtype" );
3326
3376
bod -> subtype = cpystr (Z_STRVAL_P (pvalue ));
3327
3377
}
3328
3378
if ((pvalue = zend_hash_str_find (Z_ARRVAL_P (data ), "id" , sizeof ("id" ) - 1 )) != NULL ) {
3329
3379
convert_to_string_ex (pvalue );
3380
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "body id" );
3330
3381
bod -> id = cpystr (Z_STRVAL_P (pvalue ));
3331
3382
}
3332
3383
if ((pvalue = zend_hash_str_find (Z_ARRVAL_P (data ), "description" , sizeof ("description" ) - 1 )) != NULL ) {
3333
3384
convert_to_string_ex (pvalue );
3385
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "body description" );
3334
3386
bod -> description = cpystr (Z_STRVAL_P (pvalue ));
3335
3387
}
3336
3388
if ((pvalue = zend_hash_str_find (Z_ARRVAL_P (data ), "disposition.type" , sizeof ("disposition.type" ) - 1 )) != NULL ) {
3337
3389
convert_to_string_ex (pvalue );
3390
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "body disposition.type" );
3338
3391
bod -> disposition .type = (char * ) fs_get (Z_STRLEN_P (pvalue ) + 1 );
3339
3392
memcpy (bod -> disposition .type , Z_STRVAL_P (pvalue ), Z_STRLEN_P (pvalue )+ 1 );
3340
3393
}
@@ -3344,9 +3397,11 @@ PHP_FUNCTION(imap_mail_compose)
3344
3397
SEPARATE_ARRAY (pvalue );
3345
3398
ZEND_HASH_FOREACH_STR_KEY_VAL (Z_ARRVAL_P (pvalue ), key , disp_data ) {
3346
3399
if (key == NULL ) continue ;
3400
+ CHECK_HEADER_INJECTION (key , 0 , "body disposition key" );
3347
3401
disp_param = mail_newbody_parameter ();
3348
3402
disp_param -> attribute = cpystr (ZSTR_VAL (key ));
3349
3403
convert_to_string_ex (disp_data );
3404
+ CHECK_HEADER_INJECTION (Z_STR_P (disp_data ), 0 , "body disposition value" );
3350
3405
disp_param -> value = (char * ) fs_get (Z_STRLEN_P (disp_data ) + 1 );
3351
3406
memcpy (disp_param -> value , Z_STRVAL_P (disp_data ), Z_STRLEN_P (disp_data ) + 1 );
3352
3407
disp_param -> next = tmp_param ;
@@ -3377,6 +3432,7 @@ PHP_FUNCTION(imap_mail_compose)
3377
3432
}
3378
3433
if ((pvalue = zend_hash_str_find (Z_ARRVAL_P (data ), "md5" , sizeof ("md5" ) - 1 )) != NULL ) {
3379
3434
convert_to_string_ex (pvalue );
3435
+ CHECK_HEADER_INJECTION (Z_STR_P (pvalue ), 0 , "body md5" );
3380
3436
bod -> md5 = cpystr (Z_STRVAL_P (pvalue ));
3381
3437
}
3382
3438
}
0 commit comments