X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fmessages.c;h=13e03f4066cb7fc6cca11fb0ae588846a6fde615;hb=4054f4b3c85ecab060dafd46c0d3632cadbb5803;hp=aa04ecb2dc80541da48e70f839d18cee0e6a0fe7;hpb=fa1bbdfa1cbfe84628e9e080ae694be291455f77;p=netatalk.git diff --git a/etc/afpd/messages.c b/etc/afpd/messages.c index aa04ecb2..13e03f40 100644 --- a/etc/afpd/messages.c +++ b/etc/afpd/messages.c @@ -1,140 +1,195 @@ -/* +/* + * $Id: messages.c,v 1.23 2009-11-24 15:44:40 didg Exp $ + * * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) * All Rights Reserved. See COPYRIGHT. */ #ifdef HAVE_CONFIG_H #include "config.h" -#endif +#endif /* HAVE_CONFIG_H */ +#ifdef HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ #include #include +#include +#include #include -#include -#include +#include +#include +#include #include "globals.h" #include "misc.h" + #define MAXMESGSIZE 199 /* this is only used by afpd children, so it's okay. */ -static char servermesg[MAXMESGSIZE] = ""; +static char servermesg[MAXPATHLEN] = ""; +static char localized_message[MAXPATHLEN] = ""; void setmessage(const char *message) { - strncpy(servermesg, message, MAXMESGSIZE); + strlcpy(servermesg, message, MAXMESGSIZE); } -void readmessage(void) +void readmessage(AFPObj *obj) { -/* Read server message from file defined as SERVERTEXT */ + /* Read server message from file defined as SERVERTEXT */ #ifdef SERVERTEXT - FILE *message; - char * filename; - int i, rc; - static int c; - uid_t euid; + FILE *message; + char * filename; + unsigned int i; + int rc; + static int c; + uid_t euid; + u_int32_t maxmsgsize; + + maxmsgsize = (obj->proto == AFPPROTO_DSI)?MIN(MAX(((DSI*)obj->handle)->attn_quantum, MAXMESGSIZE),MAXPATHLEN):MAXMESGSIZE; + + i=0; + /* Construct file name SERVERTEXT/message.[pid] */ + if ( NULL == (filename=(char*) malloc(sizeof(SERVERTEXT)+15)) ) { + LOG(log_error, logtype_afpd, "readmessage: malloc: %s", strerror(errno) ); + return; + } - i=0; - // Construct file name SERVERTEXT/message.[pid] - filename=malloc(sizeof(SERVERTEXT)+15); - sprintf(filename, "%s/message.%d", SERVERTEXT, getpid()); + sprintf(filename, "%s/message.%d", SERVERTEXT, getpid()); #ifdef DEBUG - syslog (LOG_DEBUG, "Reading file %s ", filename); -#endif - - message=fopen(filename, "r"); - if (message==NULL) { - syslog (LOG_INFO, "Unable to open file %s", filename); - sprintf(filename, "%s/message", SERVERTEXT); - message=fopen(filename, "r"); - } - - /* if either message.pid or message exists */ - if (message!=NULL) { - /* added while loop to get characters and put in servermesg */ - while ((( c=fgetc(message)) != EOF) && (i < (MAXMESGSIZE - 1))) { - if ( c == '\n') c = ' '; - servermesg[i++] = c; - } - servermesg[i] = 0; - - /* cleanup */ - fclose(message); - - /* Save effective uid and switch to root to delete file. */ - /* Delete will probably fail otherwise, but let's try anyways */ - euid = geteuid(); - if (seteuid(0) < 0) { - syslog(LOG_ERR, "Could not switch back to root: %m"); - } - - rc = unlink(filename); + LOG(log_debug9, logtype_afpd, "Reading file %s ", filename); +#endif - /* Drop privs again, failing this is very bad */ - if (seteuid(euid) < 0) { - syslog(LOG_ERR, "Could not switch back to uid %d: %m", euid); + message=fopen(filename, "r"); + if (message==NULL) { + /* try without the process id */ + sprintf(filename, "%s/message", SERVERTEXT); + message=fopen(filename, "r"); } - if (rc < 0) { - syslog (LOG_ERR, "Error deleting %s: %m", filename); - } + /* if either message.pid or message exists */ + if (message!=NULL) { + /* added while loop to get characters and put in servermesg */ + while ((( c=fgetc(message)) != EOF) && (i < (maxmsgsize - 1))) { + if ( c == '\n') c = ' '; + servermesg[i++] = c; + } + servermesg[i] = 0; + + /* cleanup */ + fclose(message); + + /* Save effective uid and switch to root to delete file. */ + /* Delete will probably fail otherwise, but let's try anyways */ + euid = geteuid(); + if (seteuid(0) < 0) { + LOG(log_error, logtype_afpd, "Could not switch back to root: %s", + strerror(errno)); + } + + if ((rc = unlink(filename)) != 0) + LOG(log_error, logtype_afpd, "File '%s' could not be deleted", strerror(errno)); + + /* Drop privs again, failing this is very bad */ + if (seteuid(euid) < 0) { + LOG(log_error, logtype_afpd, "Could not switch back to uid %d: %s", euid, strerror(errno)); + exit(EXITERR_SYS); + } + + if (rc < 0) { + LOG(log_error, logtype_afpd, "Error deleting %s: %s", filename, strerror(rc)); + } #ifdef DEBUG - else { - syslog (LOG_INFO, "Deleted %s", filename); - } + else { + LOG(log_debug9, logtype_afpd, "Deleted %s", filename); + } - syslog (LOG_INFO, "Set server message to \"%s\"", servermesg); -#endif - } - free(filename); + LOG(log_debug9, logtype_afpd, "Set server message to \"%s\"", servermesg); #endif + } + free(filename); +#endif /* SERVERTEXT */ } -int afp_getsrvrmesg(obj, ibuf, ibuflen, rbuf, rbuflen) - AFPObj *obj; - char *ibuf, *rbuf; - int ibuflen, *rbuflen; +int afp_getsrvrmesg(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) { - char *message; - u_int16_t type, bitmap; + char *message; + u_int16_t type, bitmap; + u_int16_t msgsize; + size_t outlen = 0; + size_t msglen = 0; + int utf8 = 0; + + *rbuflen = 0; + + msgsize = (obj->proto == AFPPROTO_DSI)?MAX(((DSI*)obj->handle)->attn_quantum, MAXMESGSIZE):MAXMESGSIZE; - memcpy(&type, ibuf + 2, sizeof(type)); - memcpy(&bitmap, ibuf + 4, sizeof(bitmap)); + memcpy(&type, ibuf + 2, sizeof(type)); + memcpy(&bitmap, ibuf + 4, sizeof(bitmap)); - switch (ntohs(type)) { - case AFPMESG_LOGIN: /* login */ - message = obj->options.loginmesg; - break; - case AFPMESG_SERVER: /* server */ message = servermesg; - break; - default: - *rbuflen = 0; - return AFPERR_BITMAP; - } + switch (ntohs(type)) { + case AFPMESG_LOGIN: /* login */ + /* at least TIGER loses server messages + * if it receives a server msg attention before + * it has asked the login msg... + * Workaround: concatenate the two if any, ugly. + */ + if (*message && *obj->options.loginmesg) { + strlcat(message, " - ", MAXMESGSIZE); + } + strlcat(message, obj->options.loginmesg, MAXMESGSIZE); + break; + case AFPMESG_SERVER: /* server */ + break; + default: + return AFPERR_BITMAP; + } - if(strlen(message)==0) + /* output format: + * message type: 2 bytes + * bitmap: 2 bytes + * message length: 1 byte ( 2 bytes for utf8) + * message: up to 199 bytes (dsi attn_quantum for utf8) + */ + memcpy(rbuf, &type, sizeof(type)); + rbuf += sizeof(type); + *rbuflen += sizeof(type); + memcpy(rbuf, &bitmap, sizeof(bitmap)); + rbuf += sizeof(bitmap); + *rbuflen += sizeof(bitmap); + + utf8 = ntohs(bitmap) & 2; + msglen = strlen(message); + if (msglen > msgsize) + msglen = msgsize; + + if (msglen) { + if ( (size_t)-1 == (outlen = convert_string(obj->options.unixcharset, utf8?CH_UTF8_MAC:obj->options.maccharset, + message, msglen, localized_message, msgsize)) ) + { + memcpy(rbuf+((utf8)?2:1), message, msglen); /*FIXME*/ + outlen = msglen; + } + else + { + memcpy(rbuf+((utf8)?2:1), localized_message, outlen); + } + } + + if ( utf8 ) { + /* UTF8 message, 2 byte length */ + msgsize = htons(outlen); + memcpy(rbuf, &msgsize, sizeof(msgsize)); + *rbuflen += sizeof(msgsize); + } + else { + *rbuf = outlen; + *rbuflen += 1; + } + *rbuflen += outlen; + *message = 0; return AFP_OK; - - /* output format: - * message type: 2 bytes - * bitmap: 2 bytes - * message length: 1 byte - * message: up to 199 bytes - */ - memcpy(rbuf, &type, sizeof(type)); - rbuf += sizeof(type); - memcpy(rbuf, &bitmap, sizeof(bitmap)); - rbuf += sizeof(bitmap); - *rbuflen = strlen(message); - if (*rbuflen > MAXMESGSIZE) - *rbuflen = MAXMESGSIZE; - *rbuf++ = *rbuflen; - memcpy(rbuf, message, *rbuflen); - - *rbuflen += 5; - - return AFP_OK; }