|  | @@ -617,6 +617,9 @@ struct mg_context {
 | 
	
		
			
				|  |  |      int workerthreadcount;     /* The amount of worker threads. */
 | 
	
		
			
				|  |  |      pthread_t *workerthreadids;/* The worker thread IDs. */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    unsigned long start_time;  /* Server start time, used for authentication */
 | 
	
		
			
				|  |  | +    unsigned long nonce_count; /* Used nonces, used for authentication */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      /* linked list of uri handlers */
 | 
	
		
			
				|  |  |      struct mg_request_handler_info *request_handlers;
 | 
	
		
			
				|  |  |  };
 | 
	
	
		
			
				|  | @@ -2760,6 +2763,14 @@ static int parse_auth_header(struct mg_connection *conn, char *buf,
 | 
	
		
			
				|  |  |      if ((s == NULL) || (*s != 0)) {
 | 
	
		
			
				|  |  |          return 0;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    nonce ^= (unsigned long)(conn->ctx);
 | 
	
		
			
				|  |  | +    if (nonce<conn->ctx->start_time) {
 | 
	
		
			
				|  |  | +        /* nonce is from a previous start of the server and no longer valid (replay attack?) */
 | 
	
		
			
				|  |  | +        return 0;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if (nonce>=conn->ctx->start_time+conn->ctx->nonce_count) {
 | 
	
		
			
				|  |  | +        return 0;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /* CGI needs it as REMOTE_USER */
 | 
	
		
			
				|  |  |      if (ah->user != NULL) {
 | 
	
	
		
			
				|  | @@ -2862,8 +2873,14 @@ static void send_authorization_request(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      char date[64];
 | 
	
		
			
				|  |  |      time_t curtime = time(NULL);
 | 
	
		
			
				|  |  | -    unsigned long nonce = (unsigned long)curtime ^ (unsigned long)conn;
 | 
	
		
			
				|  |  | +    unsigned long nonce = (unsigned long)(conn->ctx->start_time);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    (void)pthread_mutex_lock(&conn->ctx->mutex);
 | 
	
		
			
				|  |  | +    nonce += conn->ctx->nonce_count;
 | 
	
		
			
				|  |  | +    ++conn->ctx->nonce_count;
 | 
	
		
			
				|  |  | +    (void)pthread_mutex_unlock(&conn->ctx->mutex);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    nonce ^= (unsigned long)(conn->ctx);
 | 
	
		
			
				|  |  |      conn->status_code = 401;
 | 
	
		
			
				|  |  |      conn->must_close = 1;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -6197,12 +6214,17 @@ static void master_thread_run(void *thread_func_param)
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    /* Initialize thread local storage */
 | 
	
		
			
				|  |  |  #if defined(_WIN32) && !defined(__SYMBIAN32__)
 | 
	
		
			
				|  |  |      tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |      tls.is_master = 1;
 | 
	
		
			
				|  |  |      pthread_setspecific(sTlsKey, &tls);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    /* Server starts *now* */
 | 
	
		
			
				|  |  | +    ctx->start_time = (unsigned long)time(NULL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /* Allocate memory for the listening sockets, and start the server */
 | 
	
		
			
				|  |  |      pfd = (struct pollfd *) calloc(ctx->num_listening_sockets, sizeof(pfd[0]));
 | 
	
		
			
				|  |  |      while (pfd != NULL && ctx->stop_flag == 0) {
 | 
	
		
			
				|  |  |          for (i = 0; i < ctx->num_listening_sockets; i++) {
 |