The answer is that if you're compiled single-threaded, it's
perfectly legal.
If you're multi-threaded, it's not.
I guess by legal you mean that it has defined behaviour.
Yes, that's correct.
Both the C99 standard and SUS have this nice warning in it. In C99:
errno
On FreeBSD/OpenBSD my program outright core dumped and I could not
figure out why for days and days.
So you had a bug in your code. So what?
Now I have two separate builds - one built
with -D_REENTRANT -DTHREADS ... -lpthread and one without.
Only with Linux do you have the freedom of
errno is stored in Thread Local Storage (TLS). You can't link to the
global errno anymore.
For a single-threaded process, there is no distinction between thread-local
storage and a global variable. For a multi-threaded process, there is.
The same code can have a different semantic meaning
Really? So 'errno' refers to a process global in both cases?!
(Note that I
said the definition, not the implementation.)
Maybe we didn't understand each other - I don't say, that glibc without
multithread support and with it is the same. I say that linking single
threaded library which
But I must say that I believe that no-one has ever used OpenSSL
with 10'000 concurrent SSL objects.
Umm, what?! We've last tested to almost 16,384. Our first test to 10,000 was
many years ago, on servers with Pentium processors and 128MB of RAM. We've
tested on operating systems from Windows
Locking with no contention is not pretty expensive, it's darn near
free.
On systems with only one processor and nothing like hyperthreading.
Did you miss the with no contention part? An uncontended lock costs about
the same on an SMP system as on an MP system. AFAIK, hyperthreading doesn't
David Jacobson wrote:
I'm only familiar with Solaris. In that system the real stuff
in a mutex is a byte about 12 bytes into the lock structure.
On SPARC the mutex_lock function accesses it with an LDSTUB
instruction, which is a special atomic instruction that loads
the old value into a
Am I doing anything completely insane here?
IMO, writing security software by doing something that is specifically not
documented or guaranteed to work and then trying to fix every problem it
creates (at least, that you can find) is completely insane.
DS
Guaranteed to work? Who's doing the indemnification?
The point of a guarantee is that it is much less likely to change on another
machine or if a library is upgraded and compatability is claimed. Of course,
things can still go wrong.
When bugs are fixed in a library or a new version claims
On Sun, 2008-01-20 at 11:59 -0800, David Schwartz wrote:
Most definitely not. At a minimum, the definition of things
like 'errno' and
'malloc' might be different between a multithreaded build and a
non-multithreaded build. There is no supported way to combine
multithreaded
code
I should be able to create a multithreaded application using
a non-multithreaded openssl build provided that I have an ssl
context per thread.
Most definitely not. At a minimum, the definition of things like 'errno' and
'malloc' might be different between a multithreaded build and a
I have an application which needs to do encryption and decryption of
files which may not fit in main memory. I'm using the PKCS#7
enveloped-data format, and have implemented the encryption side of
things using Steve Henson's work as a reference:
Now it's time to implement streaming
Come down to the details, I am having trouble using select() a
read/write file descriptor to make BIO_do_connect a non-blocking call,
before BIO_do_connect() returns, BIO_get_fd() will return -1. Without a
file descriptor, how can I use select()?
Now that I think about, maybe your
This question have been discussed since I saw a long thread of it.
Come down to the details, I am having trouble using select() a
read/write file descriptor to make BIO_do_connect a non-blocking call,
before BIO_do_connect() returns, BIO_get_fd() will return -1. Without a
file descriptor,
from p.ponnusamy,
i like to develop the paper titled comparison studies
between pre-shared and public key exchange in transport layer
security. i need some guidance for it. which platform would be better
for this ? which language i can choose c,c++,java or j2me ?
Either:
1) The
Hi,
the 7-Zip archiver has recently become very popular because of
its good compression rate;
f.e. recent snapshot is about 34% smaller when packed with 7z
compared to tar.gz:
-rw-r--r-- 1 root root 2484981 Jan 5 17:28 openssl-SNAP-20080105.7z
-rw-r--r-- 1 root root 3781438 Jan 5
looks to me like tar+lzma is the way to go, not 7z
In my quick test, lzma got a 7.6, beating 7z by a negligible margin.
I think it largely comes down to whether any of these are popular enough to
justify the effort of offering in that format. We've been down this road
before in the transition
I have a problem about OpenSSL proxy server rebooting.
OpenSSL proxy server could not be restarted after killing,
and I find the root cause:
On Linux OS, if there is a socket binding a port, after the socket
is closed or the program exit normally, the port could not be release
at once, if
Nanno Langstraat wrote:
* Remote side completely closes its socket.
This causes read()=0 and write()=-1/EPIPE on the local side.
* Our TCP proxy gets read()==0 on the TCP socket.
* In response, our proxy does shutdown(WR) on the local drain file
descriptor (the other
I want to repeat: it's also OK by me if the documentation *explicitly*
says somewhere
SSL can not operate half-duplex like TCP can. SSL_read()==0 means
the connection is truly dead. You should not do SSL_write() anymore,
and you can not use the results of SSL_want*() anymore for
This goes pear-shaped as follows:
* The SSL connection is made and used
* The remote side closes its file descriptor (e.g. process killed,
TCP shutdown(RD))
* Local SSL_read() returns 0. The app event loop sets a flag and
makes sure it never calls SSL_read() again.
Nanno Langstraat:
Quote chapter and verse of the OpenSSL API documentation, or desist from
such vehement statements.
You can not scold an API user for violating rules that are not in the
documentation.
I already claimed that the application programmer is not given the
knowledge that this
TCP can do half-duplex connections (read side shut down, write side
still operating).
OpenSSL can not do half-duplex connections.
True.
An innocent OpenSSL API user is not told that OpenSSL can not do
half-duplex connections and that he must not try.
Nonsense. It is impossible for him
Nanno Langstraat wrote:
You have become very familiar with the internal structure and behaviour
of the OpenSSL implementation, but you now appear (to me) to be unable
to recognize things as non-obvious and non-reasonable to an honest new
OpenSSL API programmer.
You have to be extremely
The scenario you are describing is simply impossible.
It is possible (even very likely) that the upstream plaintext buffer in
the stunnel-like half-duplex-handling proxy application happens to be
empty, but that the local plaintext source file descriptor is still open.
True.
The
If I'm misunderstanding the man page and/or the source code
please speak up.
My man page says:
If the underlying BIO is non-blocking, SSL_shutdown() will also
return
when the underlying BIO could not satisfy the needs of SSL_shutdown()
to continue the handshake. In this
Thor Simon wrote:
On Sat, Sep 29, 2007 at 03:11:18PM -0700, Davide Libenzi wrote:
Heh? Wait for readwrite? Consider such code:
for (;;) {
err = SSL_shutdown();
code = SSL_get_error(ssl, err);
if (code == SSL_ERROR_SYSCALL) {
If the SSL implementation works in this way then trying to shoe-horn SSL
into a similar 3 argument API as the kernel was a bad design decision.
I agree. In other words, the nature of SSL demands a more complex API than
TCP.
Its probably a bit late in the game to go changing the SSL_write()
AGAIN... since I'm not using SSL_MODE_ENABLE_PARTIAL_WRITE,
I would expect no part of the buffer I provide to be used in a write
failure situation and therefore there should be no concept of a write
buffer moving... the next write is a new and unrelated write.
To clarify, I would expect that
David, no it's not that simple.
1) You specifically did not tell OpenSSL to accept a moving
write buffer.
Correct, I did not tell OpenSSL to accept a moving write
buffer... but then
again, why would I?
Because your write buffer moves.
If I haven't set SSL_MODE_ENABLE_PARTIAL_WRITE,
Of course it is sane; it is sane for OpenSSL to provide clear
demarkation of exactly which data is committed and which data is
uncommitted.
Consider the following scenario:
1) You ask OpenSSL to send 16 bytes.
2) OpenSSL accepts/encrypts those 16 bytes.
3) This results in a 24 byte record.
The idea.h header file is not installed when openssl 0.9.7m is
compiled on windows system. This header file is included from
evp.h header file.
Because the IDEA algorithm is covered by patents in some parts of the world,
many compiled builds of OpenSSL don't include it. The evp.h header file
I don't think -march=pentium4 is going to work on an IA64, and I have my
doubts about sse3 too.
Yeah, I misread the original post. I still recommend comparing using the
appropriate optimization flags for each compiler. If you're going to compare
them just based on performance, you should allow
Using the Intel 9.1 compiler on an IA64 system the performance of
AES and (to a lesser extent) other algorithms implemented in
assembly language is less than that using gcc. I've included the
speed output for several of the algorithms below.
Is this a know issue and is there a workaround
Using the Intel 9.1 compiler on an IA64 system the performance of
AES and (to a lesser extent) other algorithms implemented in
assembly language is less than that using gcc. I've included the
speed output for several of the algorithms below.
Is this a know issue and is there a workaround
[EMAIL PROTECTED] ([EMAIL PROTECTED]) terminated by signal BUS (invalid
address alignment)
0x7d24fab8: t_delete+0x00f8:stx %o0, [%g4 + 16]
current thread: [EMAIL PROTECTED]
[1] t_delete(0x11c303480, 0x0, 0x7f268340, 0x2000,
0x2190, 0x1004e4290), at
I searched the archives, but didn't find any hits for what I want. If this
has already been discussed, please let me know how to improve my search
string.
On to my question: I know DER is a subset of BER, so therefore
OpenSSL does
write to BER, but can we write to any other BER encodings
Im tearing my hair out here with what is probably a stupid problem.
I'm new to openssl , rsa, etc... , so bear with me please:)
[snip]
Ok then, i know the key needs to be in PEM format, for PHP /
openssl... but, i can't get it recognized at all by openssl.
[snip]
Ok, so i guess i do somehow
For example, if we are running under Unix-style kernel, we can make
stat calls on both files. And if both st_dev and st_ino fields of
the resulting stat structures are same, we should consider files same.
Why? Suppose the filesystem internally uses inodes larger than the st_ino
field. Is it
On 2007.04.19 at 11:59:39 -0700, David Schwartz wrote:
This is not nearly as simple as you might think. Are 'foo.txt'
and 'Foo.txt' the same file? What about 'directory/file.txt' and
'symlink/file.txt'?
I don't see how you can do this without making assumptions about the
semantics
I have been using openssl for some personal home-use encryption, and
recently overwrote an input file while using openssl bf accidentally
because bash's autocompletion put in the input file's name when I
started typing the same name (minus bf at the end) for the output and I
carelessly
If kevents are the only direct asynchronous notification mechanism for
this hardware, then it doesn't seem unreasonable to require the
application to use kevent() for high performance. OpenSSL could
provide a function to return the set of (struct kevent)s for a given
SSL connection, which
On 4/15/07, David Schwartz [EMAIL PROTECTED] wrote:
You could easily implement the poll, select, and kevent
semantics with just
this function. I can't think of any reason a more complex
implementation would be any better.
One reason, as suggested by Thor, is that OpenSSL sometimes
If we were to add SSL_poll() (my preference) or SSL_select()
(perhaps more portable) to the API, the OpenSSL library could add
events to the set the application is waiting on -- so it could
wake the application up when crypto requests had finished and
SSL_read()/SSL_write() were possible.
int SSL_poll(struct pollfd *fds, nfds_t nfds, int timeout,
struct SSL_pollctx *sctx, nfds_t nsctx);
I like this approach a lot. Could someone with great familiarity of
OpenSSL's guts give the five minute explanation of what's involved in making
this happen? I can start
Richard Salz:
Suppose another thread does this:
*p=99;
*p=98;
Out of scope -- the C standard does not define ANY semantics for
multiple
threads of execution.
Exactly. The original example was:
extern volatile char* p;
int i, j;
i = *p;
j = *p;
This is the precise optimization that 'volatile' inhibits.
For single-threaded code, you are right. But we are talking about
multi-threaded code.
'volatile'
requires that the value not be cached in cheap-to-access locations
like registers, instead being re-loaded from expensive-to-access
A read of a 'volatile uint64_t', btw, is supposed to make sure that it
reads from the original memory locations, not cached copies of it in
register or spread across multiple registers.
Which it doesn't do on any platform I know of. On every platform, 'volatile'
reads through the caches and
Darryl Mile wrote:
A compiler will not generate a store instruction to put back a
cached_copy into the variable location. Principally because there was
no assignment operation in the original code and because even a
non-optimizing compiler knows it can just dump the cached_copy
Richard Salz wrote:
Kyle's claim about things like cache's and registers is wrong, not even
sort-of right. The standard talks about only in terms of
sequence points,
and volatile limits what can be done in terms of sequence points. So
extern volatile char* p;
int i, j;
So the point you are trying to make is, while the function would
solve the
purpose of freeing the compression methods, However the lock are
not really
required in the usage secnario of this function?
If the usage scenario is solely final shutdown of the library, then the lock
is not
David seems to be thinking ahead into the realms of CPUs that have not
been invented yet.
Exactly. That's why there are standards and guarantees. If you follow the
standards and rely on the guarantees you have, your code will work on all
future platforms that provide those same guarantees
1287 void SSL_free_comp_methods(void)
1288 {
1289 if (ssl_comp_methods == NULL)
1290 return;
1291 CRYPTO_w_lock(CRYPTO_LOCK_SSL);
1292 if (ssl_comp_methods != NULL)
1293 {
1294 sk_SSL_COMP_pop_free(ssl_comp_methods,CRYPTO_free);
For POSIX threads, the result of reading a variable in one
thread while it
might be modified in another thread is undefined. Line 1289 and
1290 should
be removed.
Not this old chestnut again.
Like it or not, it's a fact.
I can't name a CPU in which an aligned load/store of a
Oh. I'm sorry. Someone needs to use a keyword 'volatile'.
Sorry, doesn't help.
Bingo. Problem solved on the improper optimization issue.
What specification says that 'volatile' causes any particular semantics across
threads? I must not have read that one. The 'volatile' keyword is only
Hi!
I have an example case where by the unused memoy allocated by
SSL_library_init when not freed, would accumulate.
There is an application which takes services from some of the
libraries say
A, B and C.
These libraries are dynamically loaded and unloaded into the
application as
and
HI!
Thanks again for highlighting those issues. What would be the
best way for
the application using those pluggins to avoid this issue of
SSL_library_init()?
There are really two good ways that ensure that all problems are resolved.
Other ways just deal with problems as they crop up and
If we say that the call SSL_library_init() would initialze some data
structures which have process scope and are initialized only once.
In such case what is the problem in having a *single* function
which exacly
cleans up those data structures at the time of process termination?
See my
Is it required to call SSL_library_init() if I only want to use
some crypto
functionalities?
All SSL_library_init does is add ciphers and digests to the EVP table. If
you don't need any ciphers and digests accessible through the EVP interface
or you add those ciphers and digests yourself, you
diff -ru openssl-0.9.8e/ssl/ssl_rsa.c openssl-0.9.8e-hacked/ssl/ssl_rsa.c
--- openssl-0.9.8e/ssl/ssl_rsa.c 2005-04-09 08:52:41.0 +1000
+++ openssl-0.9.8e-hacked/ssl/ssl_rsa.c 2007-03-19
09:03:15.0 +1100
@@ -728,6 +728,9 @@
goto end;
}
Keepin it apart from the memory leak, i would like to know by
example how a
perfect cleanup can casue performance problems?
One common case goes like this:
1) You have an object you create very early in the library initialization.
2) The object is accessed a lot, and having to check if it's
Could you please tell me where in the manual pages or in which
document that is documented? That would be really helpful.
Didn't this all start because you didn't trust the documentation?
Until now the man page for SSL_read reads:
WARNING
When an SSL_read() operation has to
When an SSL_read() operation has to be repeated because of
SSL_ERROR_WANT_READ
or SSL_ERROR_WANT_WRITE, it must be repeated with the same arguments.
I'm having a hard time to understand the openssl code to confirm that
SSL_read doesn't need the same buffer on retries.
And on the
Oi. Don't do that.
Why not?
Because it's a pure pessimization whose sole purpose is to suppress a
bogus
warnings that very, very few people even see, when there's already a way to
suppress those warnings that doesn't impose costs on people who don't care
about them because they'll
Valgrind runs on unmodified binaries - and it's not always
possible to get someone else to recompile their code so that
you can find problems. OpenSSL is used in commercial products
where source isn't always available.
Valgrind *can* run on unmodified binaries, but when you do that, you get
So HT flag is no longer HyperThreading, but something else...
Will look into
it... There is another place HTT flag is checked and it's AES...
yeah HT flag now basically means multi-threading or multi-core
package... because when amd/intel went dual core they didn't want silly
license
The equivalent of the offending line would be
foo((double *)(void *) j);
since any access through a void pointer CAN change the value.
'(double *)(void *)' does not keep some sort of remnant of the 'void *'. The
final cast renders the end-result a 'double *' and negates the 'void *'. You
I found the rule -- at least for C99. It is ISO 9899:1999 section
6.2.5, rule 26 and footnote 39:
26) A pointer to void shall have the same representation and alignment
requirements as a
pointer to a character type. Similarly, pointers to qualified or unqualified
versions of
An object may be the type of its last cast -- but it also can't
exactly lose the benefit/cost of being cast to a pointer to an
undefined type. As soon as you undefine the type of a pointer, it
loses the remnant of ever having had the initial type in the first
place.
Right, but that doesn't
But you can pass 'X509 **' as 'void *'. So...
void x509func(void* p) { X509** pp = (X509**)p; ... }
void trampoline(void* p) { x509func(p); }
void caller(void) { X509* p; trampoline(p); }
should (MUST?) work just fine.
/r$
When I change my test programs
Are you sure that problem is in cast ?
$ cat test.c
main() {
int j=2;
double *d=(double*)j;
*d=1.0;
printf(%d %e\n, j, *d);
printf(%d %e\n, j, *d);
}
gcc -O2 test.c ./a.out
2 1.00e+00
0 1.00e+00
Same result in case with line double *d=j; (but expected warning:
davids simple -- if you are going to call a function whose types you
davids don't know (through a prototype), you must cast each type you
davids pass to the type the function expects. End of story. OpenSSL
davids does not do this. This is not valid C whether or not the type
davids sizes
Once KR is included, the situation becomes a lot less clear. Also, as I
read the thread on the GCC list, it looks like the situation is further
complicated by their desire to avoid an internal compiler error.
Also**2,
I don't know what you mean by C's aliasing rules; to me that brings to
But it gets cast back to the correct type before it is called. These
casts are done the way they are to get type-safety. Removing that option
strikes me as a bad thing.
It does not. Look closely at how these functions work:
char *PEM_ASN1_read_bio(char *(*d2i)(), const char *name, BIO *bp,
x is still just a pointer to data - so it's the same
length in any case, all pointers to lvalues are the
same length in C. The only issue there is whether it's
aligned correctly - that's the programmers problem.
Length is not the issue. There is no rule that says that two types must be
On Tue, Nov 07, 2006, Bernhard Rosenkraenzer wrote:
gcc 4.2 no longer allows function casting - which is used
rather heavily by
openssl. (To make things worse, it compiles but inserts abort()
statements
resulting in app crashes).
Ugh, I would've thought that flagging a compiliation
4.I use 'WSAEventSelect'. Windows assumes that writing to socket
is possible all the time, so you don't have to check socket's
possibilty to write if you want to write, like you do it using
'select' statement. Only if 'send' will fail with WSAEWOULDBLOCK
error code windows will send
The long version: We run security check software, which makes connections
with various services, calls up the header, and then tells us that based
upon the version it read in the header, this service has certain
vulnerabilities.
You mean it might have certain vulnerabilities. You
The long version: We run security check software, which makes
connections
with various services, calls up the header, and then tells us that based
upon the version it read in the header, this service has certain
vulnerabilities.
I just have to say one more thing:
You
The OPENSSL_gmtime in o_time.c (that gets called from other places
like ASN1_UTCTIME_cmp_time_t in a_utctm.c) does not use the safe
version of gmtime in lots of platforms including:
OPENSSL_SYS_WIN32
OPENSSL_SYS_OS2
__CYGWIN32__
OPENSSL_SYS_MACOSX
OPENSSL_SYS_SUNOS
This could cause problems in
In message
[EMAIL PROTECTED]
com on Tue, 16 May 2006 12:27:27 -0400, Richard Salz
[EMAIL PROTECTED] said:
rsalz As for BSD/advertising dicussions, the SSLeay license is
rsalz characterized as BSD with copyright. It's not pure BSD, and
rsalz so whether or not the current BSD license has
1. When using OpenSSL for signing data, and for SSL sessions
(both client side and server side), should I use the /dev/random instead?
IMO, if you're using the random data just to seed a PRNG, there is no
rational reason to insist on using /dev/random instead of /dev/urandom. The
only
BTW why will I run into trouble at 2015 it should be good up to 2037?
Am I missing some thing?
You said your system signs certificates that are valid for as long as 25
years. In 2015, therefore, you may encounter certificates that expire in
2040.
DS
00 20 : Illegal DER, leading 00 not needed
00 80 : Legal, leading 00 needed to make number positive
FF 03 : Legal, leading FF needed to make number negative
FF D0 : Illegal DER, FF not needed
Note that these are all legal BER and are all perfectly valid and
meaningful integer
I will not get certificates today for after 2045 because the
certificates that I am checking are certificates that already past a
validation check and have been inserted into my cache system, therefor
it is a certificate signed by our own system which does not sign for
more then 25 year.
My mistake it was ASN1_TIME that is correct.
But any way, I don't see a reason why I should not be able to convert
it, if I don't care for milliseconds, time_t can represent times for
up to 2038, so It should be ok to convert it to the time_t.
Any ideas, the ASN1_cmp_time does much more
Alright, there's a SEVERE disconnect here versus the description of an
integer as described in the thread openssl can don' t handle 20 Octes
long Serial Numbers RFC 3280.
If you think there's a disconnect, you are confused.
This needs to be rectified soonest.
There is no
openssl prime 2
2 is not prime
openssl version openssl-0.9.8a
This is a known issue. The prime testing code was designed to test large
primes.
DS
__
OpenSSL Project
Hello all!
I find some problem in OpenSSL when I use it for connecting to POP3s
(POP3 over SSL/TLS, port 995) server. When I use command retr it's
work fine. When I use RETR OpenSSL print some error.
Computer: Cel-633, RAM 192, HDD 10Gb
OS: WinXP SP2
OpenSSL: OpenSSL 0.9.8a 11 Oct 2005
I am having a lot of problems importing a certificate made in openssl
into a phone, but I can get a keytool certificate imported. The only
thing is that I need to change the V1 cert (keytool only makes V1) to a
V3 cert - can openssl modify a cert to a V3 (without changing anything
else)?
This is a follow on from my last post as the text lost its formatting.
How do I change the utc time of a certificate to a smaller format
(whilst creating a cert):
18082107Z - there are lots of zeros in this format, openssl
gives less.
There is never more than one way to
Thanks for your point. However, I think you
misinterpreted my problem.
Actually, you have misinterpret your own problem. ;)
I know BER is a superset of DER, so we can use DER in
places where BER is expected.
Exactly.
However, my case is reversed. I am trying to use BER
Thanks, David.
I am stuck exact at how to convert BER to DER.
If I can convert BER to DER, then my problem is
solved.
Dr. Steve said there is no such conversion routine in
OpenSSL...
That is not your program. If that were the problem, the solution would
simply be to read your
Hi,
May I ask how to use openssl API implement a ssh
client in C++/Unix?
Part of this communication project is to use ssh/ssl
client communicate with the sshd server on the other
site and push local configuration files to the
remote machine.
Googling for openssl ssh immediately
On Fri, 8 Apr 2005, David Schwartz wrote:
No. The C standard is not telling the compiler what to do.
It is saying
what the system must do when it runs the particular source code. If the
compiler cannot generate code that makes the system as a whole
comply with
the standard
It strikes me that the H/W designers have played a bit fast and
loose with
the cache consistency issue here
For the vast majority of cases, this is a pure speed boost. For the tiny
number of cases where it causes a problem, you use mutexes.
- I believe I understand the C/C++
On Thursday 07 April 2005 16:39, David Schwartz wrote:
A bit off-topic, but...
If you mean 'volatile', no, that doesn't do anything. Specifically,
'volatile' has no special semantics for multi-processors. There may be
specific compilers where it has such semantics, but the standard
I mean that if the order of memory write visibility between
processors can't
be g'teed, than a whole lot MORE than just DCLP crashes and burns ... How
in that case can anyone write safe MP code?
D.
The only correct and safe way to do it is with mutexes or their
equivalent.
DCLP
Since aquiring the mutex is already on the 'slow' track,
couldn't you
just aquire a second (pointless) mutex inside the first around only the
'initialized=1;' assignment? If mutexes resolve the initial situation
then they must be implemented with a memory fence (in the itanium
model), and
I am trying to use ssl_read in the loop for receiving the data
of
unknown size ( say 988 bytes for now ). But it fails to read after a
single pass. Everytime it exits with ret = 32 and error=SSL_ERROR_NONE.
Am I missing something here .. Please find attached the code snippet. Is
101 - 200 of 243 matches
Mail list logo