diff -crB motion-3.2.12/conf.c motion-3.2.12_WebAuthentication/conf.c
*** motion-3.2.12/conf.c	2010-11-22 20:15:43.000000000 +0200
--- motion-3.2.12_WebAuthentication/conf.c	2010-11-22 20:31:51.000000000 +0200
***************
*** 89,94 ****
--- 89,95 ----
      webcam_maxrate:             1,
      webcam_localhost:           1,
      webcam_limit:               0,
+     webcam_authentication:      NULL,
      control_port:               0,
      control_localhost:          1,
      control_html_output:        1,
***************
*** 933,938 ****
--- 934,948 ----
      print_int
      },
      {
+     "webcam_authentication",
+     "# Authentication for the webcam server. Syntax username:password\n"
+     "# Default: not defined (Disabled)",
+     1,
+     CONF_OFFSET(webcam_authentication),
+     copy_string,
+     print_string
+     },    
+     {
      "control_port",
      "\n############################################################\n"
      "# HTTP Based Control\n"
diff -crB motion-3.2.12/conf.h motion-3.2.12_WebAuthentication/conf.h
*** motion-3.2.12/conf.h	2010-11-22 20:15:43.000000000 +0200
--- motion-3.2.12_WebAuthentication/conf.h	2010-11-22 20:51:00.000000000 +0200
***************
*** 64,69 ****
--- 64,70 ----
      int webcam_maxrate;
      int webcam_localhost;
      int webcam_limit;
+     const char *webcam_authentication;
      int control_port;
      int control_localhost;
      int control_html_output;
Only in motion-3.2.12_WebAuthentication: conf.h~
diff -crB motion-3.2.12/webcam.c motion-3.2.12_WebAuthentication/webcam.c
*** motion-3.2.12/webcam.c	2010-11-22 20:15:43.000000000 +0200
--- motion-3.2.12_WebAuthentication/webcam.c	2010-11-22 20:24:27.000000000 +0200
***************
*** 26,31 ****
--- 26,35 ----
  #include <sys/fcntl.h>
  
  
+ extern const char* bad_request_response;
+ extern const char* bad_method_response_template;
+ extern const char *request_auth_response_template;
+ 
  /* This function sets up a TCP/IP socket for incoming requests. It is called only during
   * initialisation of Motion from the function webcam_init
   * The function sets up a a socket on the port number given by _port_.
***************
*** 81,87 ****
          ioctl(sc, FIONBIO, &i);
          return sc;
      }
!     
      motion_log(LOG_ERR, 1, "accept()");
  
      return -1;
--- 85,91 ----
          ioctl(sc, FIONBIO, &i);
          return sc;
      }
!      
      motion_log(LOG_ERR, 1, "accept()");
  
      return -1;
***************
*** 201,210 ****
--- 206,357 ----
      return tmpbuffer;
  }
  
+ /* Try to authenticate the client before sending the images */
+ static unsigned short int webcam_auth_client(int client_socket, char *auth)
+ {
+     char buffer[1024] = {'\0'};
+     unsigned short int length = 1023;
+     int warningkill;
+     ssize_t nread = 0, readb = -1;
+     fd_set fdread;
+     struct timeval timeout;
+ 
+     timeout.tv_sec = 0;
+     timeout.tv_usec = 0;
+     FD_ZERO(&fdread);
+     FD_SET(client_socket, &fdread);
+     
+     if (select(client_socket+1, &fdread, NULL, NULL, &timeout) > 0) {
+         nread = read (client_socket, buffer, sizeof(buffer));
+     } 
+     
+     if (nread <= 0) {
+         return 0;
+     }
+   
+     char method[10]={'\0'};
+     char url[512]={'\0'};
+     char protocol[10]={'\0'};
+     char *authentication = NULL;
+ 
+     buffer[nread] = '\0';
+ 
+     warningkill = sscanf (buffer, "%9s %511s %9s", method, url, protocol);
+ 
+     while ((strstr (buffer, "\r\n\r\n") == NULL) && (readb != 0) && (nread < length)) {
+         readb = read (client_socket, buffer+nread, sizeof (buffer) - nread);
+ 
+         if (readb == -1) {
+             nread = -1;
+             break;
+         }
+ 
+         nread +=readb;
+                 
+         if (nread > length) {
+             motion_log(LOG_ERR, 1, "webcam End buffer reached waiting for buffer ending");
+             break;
+         }
+         buffer[nread] = '\0';
+     }
+ 
+     /* Make sure the last read didn't fail.  If it did, there's a
+        problem with the connection, so give up.  */
+     if (nread == -1) {
+         motion_log(LOG_ERR, 1, "webcam READ");
+         return 0;
+     }
+ 
+     /* Check Protocol */
+     if (strcmp (protocol, "HTTP/1.0") && strcmp (protocol, "HTTP/1.1")) {
+         /* We don't understand this protocol.  Report a bad response.  */
+         warningkill = write (client_socket, 
+                              bad_request_response, 
+                              sizeof (bad_request_response));
+         return 0;
+     }
+ 
+     if (strcmp (method, "GET")) {
+         /* This server only implements the GET method.  If client
+            uses other method, report the failure.  */
+         warningkill = write (client_socket, 
+                              bad_method_response_template, 
+                              strlen (bad_method_response_template));
+         return 0;
+     }
+ 
+     if ((authentication = strstr(buffer,"Basic")) ) {
+         char *end_auth = NULL;
+         authentication = authentication + 6;
+ 
+         if ((end_auth  = strstr(authentication,"\r\n")) ) {
+             authentication[end_auth - authentication] = '\0';
+         } else {
+             warningkill = write (client_socket, 
+                                  request_auth_response_template, 
+                                  strlen (request_auth_response_template));
+             return 0;
+         }
+ 
+         if (strcmp(auth, authentication)) {
+             warningkill = write (client_socket, 
+                                  request_auth_response_template, 
+                                  strlen (request_auth_response_template));
+             return 0;
+         } else {
+             /* Successfull authentication */
+             return 1;
+         }
+     } else {
+         // Request Authorization
+         warningkill = write (client_socket, 
+                              request_auth_response_template, 
+                              strlen (request_auth_response_template));
+         return 0;
+     }
+ 
+     return 0;
+ }
  
  static void webcam_add_client(struct webcam *list, int sc)
  {
      struct webcam *new = mymalloc(sizeof(struct webcam));
+     memset(new, 0, sizeof(struct webcam));
+     new->socket = sc;
+     new->auth = FALSE;
+ 
+     new->prev = list;
+     new->next = list->next;
+     
+     if (new->next)
+         new->next->prev=new;
+     
+     list->next = new;
+ }
+ 
+ static void webcam_remove_client(struct webcam *client)
+ {
+     close(client->socket);      
+ 
+      if (client->tmpbuffer != NULL) {
+          if (client->tmpbuffer->ptr != NULL)
+              free(client->tmpbuffer->ptr);
+         free(client->tmpbuffer);
+     }
+          
+     if(client->prev != NULL) {
+         client->prev->next = client->next;
+         if (client->next)
+             client->next->prev = client->prev;
+     } else {
+         motion_log(LOG_ERR, 0, "Null pointer in webcam_remove_client");
+     }
+     
+     free(client);
+ }
+ 
+ static void webcam_write_header(struct webcam *client)
+ {
      static const char header[] = "HTTP/1.0 200 OK\r\n"
              "Server: Motion/"VERSION"\r\n"
              "Connection: close\r\n"
***************
*** 214,238 ****
              "Pragma: no-cache\r\n"
              "Content-Type: multipart/x-mixed-replace; boundary=--BoundaryString\r\n\r\n";
  
!     memset(new, 0, sizeof(struct webcam));
!     new->socket = sc;
!     
!     if ((new->tmpbuffer = webcam_tmpbuffer(sizeof(header))) == NULL) {
          motion_log(LOG_ERR, 1, "Error creating tmpbuffer in webcam_add_client");
      } else {
!         memcpy(new->tmpbuffer->ptr, header, sizeof(header)-1);
!         new->tmpbuffer->size = sizeof(header)-1;
      }
-     
-     new->prev = list;
-     new->next = list->next;
-     
-     if (new->next)
-         new->next->prev=new;
-     
-     list->next = new;
  }
  
  
  static void webcam_add_write(struct webcam *list, struct webcam_buffer *tmpbuffer, unsigned int fps)
  {
--- 361,412 ----
              "Pragma: no-cache\r\n"
              "Content-Type: multipart/x-mixed-replace; boundary=--BoundaryString\r\n\r\n";
  
!     if ((client->tmpbuffer = webcam_tmpbuffer(sizeof(header))) == NULL) {
          motion_log(LOG_ERR, 1, "Error creating tmpbuffer in webcam_add_client");
      } else {
!         memcpy(client->tmpbuffer->ptr, header, sizeof(header)-1);
!         client->tmpbuffer->size = sizeof(header)-1;
      }
  }
  
+ static void webcam_authenticate(struct context *cnt)
+ {
+     struct webcam *client = cnt->webcam.next;
+     char * auth = cnt->conf.webcam_authentication;
+     
+     while (client) {
+         if (!client->auth) {
+             if (auth != NULL) {
+                 char *authentication = NULL;
+                 char *userpass = NULL;
+                 size_t auth_size = strlen(auth);
+         
+                 authentication = (char *) mymalloc(BASE64_LENGTH(auth_size) + 1);
+                 userpass = mymalloc(auth_size + 4);
+                 /* base64_encode can read 3 bytes after the end of the string, initialize it */
+                 memset(userpass, 0, auth_size + 4);
+                 strcpy(userpass, auth);
+                 base64_encode(userpass, authentication, auth_size);
+                 free(userpass);     
+          
+                 if (webcam_auth_client(client->socket, authentication)) {
+                     /* The authentication has succeded. */
+                     client->auth = TRUE;
+                     webcam_write_header(client);                            
+                 } else {
+                     /* Client authentication has failed. Remove the client. */
+                     webcam_remove_client(client);
+                     cnt->stream_count--;
+                 }
+             } else {
+                 /* No authentication needed.*/
+                 webcam_write_header(client);
+                 client->auth = TRUE;
+             }
+         }
+         client = client->next;
+     }
+ }
  
  static void webcam_add_write(struct webcam *list, struct webcam_buffer *tmpbuffer, unsigned int fps)
  {
***************
*** 364,374 ****
       */
      if ((cnt->stream_count < DEF_MAXSTREAMS) &&
          (select(sl+1, &fdread, NULL, NULL, &timeout) > 0)) {
          sc = http_acceptsock(sl);
!         webcam_add_client(&cnt->webcam, sc);
!         cnt->stream_count++;
      }
      
      /* call flush to send any previous partial-sends which are waiting */
      webcam_flush(&cnt->webcam, &cnt->stream_count, cnt->conf.webcam_limit);
      
--- 538,553 ----
       */
      if ((cnt->stream_count < DEF_MAXSTREAMS) &&
          (select(sl+1, &fdread, NULL, NULL, &timeout) > 0)) {
+         
          sc = http_acceptsock(sl);
! 
! 	webcam_add_client(&cnt->webcam, sc);
! 	cnt->stream_count++;
      }
      
+     /* Check authentication */
+     webcam_authenticate(cnt);
+     
      /* call flush to send any previous partial-sends which are waiting */
      webcam_flush(&cnt->webcam, &cnt->stream_count, cnt->conf.webcam_limit);
      
diff -crB motion-3.2.12/webcam.h motion-3.2.12_WebAuthentication/webcam.h
*** motion-3.2.12/webcam.h	2010-11-22 20:15:43.000000000 +0200
--- motion-3.2.12_WebAuthentication/webcam.h	2010-11-22 20:34:53.000000000 +0200
***************
*** 33,38 ****
--- 33,39 ----
      struct webcam_buffer *tmpbuffer;
      long filepos;
      int nr;
+     int auth;
      unsigned long int last;
      struct webcam *prev;
      struct webcam *next;
diff -crB motion-3.2.12/webhttpd.c motion-3.2.12_WebAuthentication/webhttpd.c
*** motion-3.2.12/webhttpd.c	2010-11-22 20:15:43.000000000 +0200
--- motion-3.2.12_WebAuthentication/webhttpd.c	2010-11-22 20:36:45.000000000 +0200
***************
*** 59,65 ****
      "Content-type: text/plain\r\n\r\n";
  
  
! static const char* bad_request_response =
      "HTTP/1.0 400 Bad Request\r\n"
      "Content-type: text/html\r\n\r\n"
      "<html>\n"
--- 59,65 ----
      "Content-type: text/plain\r\n\r\n";
  
  
! const char* bad_request_response =
      "HTTP/1.0 400 Bad Request\r\n"
      "Content-type: text/html\r\n\r\n"
      "<html>\n"
***************
*** 169,175 ****
      "Content-type: text/plain\n\n"
      "Not Valid Command\n";
  
! static const char* bad_method_response_template =
      "HTTP/1.0 501 Method Not Implemented\r\n"
      "Content-type: text/html\r\n\r\n"
      "<html>\n"
--- 169,175 ----
      "Content-type: text/plain\n\n"
      "Not Valid Command\n";
  
! const char* bad_method_response_template =
      "HTTP/1.0 501 Method Not Implemented\r\n"
      "Content-type: text/html\r\n\r\n"
      "<html>\n"
***************
*** 184,190 ****
      "Content-type: text/plain\r\n\r\n"
      "Method Not Implemented\n";
  
! static const char *request_auth_response_template=
      "HTTP/1.0 401 Authorization Required\r\n"
      "WWW-Authenticate: Basic realm=\"Motion Security Access\"\r\n";
  
--- 184,190 ----
      "Content-type: text/plain\r\n\r\n"
      "Method Not Implemented\n";
  
! const char *request_auth_response_template=
      "HTTP/1.0 401 Authorization Required\r\n"
      "WWW-Authenticate: Basic realm=\"Motion Security Access\"\r\n";
  
